Browse Source

- Split token stream and parser (will be important for the IDE)

- Can now parse directly from a token stream (doesn't have to be a file)
- Changed the way libraries are stored in projects
- Tokens no longer contain their position (will be important for the IDE)
Stan Hebben 6 years ago
parent
commit
6feb3f4246
23 changed files with 818 additions and 617 deletions
  1. 34
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/Library.java
  2. 4
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/Main.java
  3. 12
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java
  4. 23
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java
  5. 2
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/ModuleReference.java
  6. 22
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourceFile.java
  7. 31
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourcePackage.java
  8. 0
    4
      Parser/src/main/java/org/openzen/zenscript/lexer/Token.java
  9. 411
    0
      Parser/src/main/java/org/openzen/zenscript/lexer/TokenParser.java
  10. 18
    374
      Parser/src/main/java/org/openzen/zenscript/lexer/TokenStream.java
  11. 1
    10
      Parser/src/main/java/org/openzen/zenscript/lexer/ZSToken.java
  12. 176
    0
      Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenParser.java
  13. 7
    156
      Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenStream.java
  14. 0
    5
      Parser/src/main/java/org/openzen/zenscript/parser/ParseException.java
  15. 8
    4
      Parser/src/main/java/org/openzen/zenscript/parser/ParsedFile.java
  16. 2
    1
      Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedEnumConstant.java
  17. 3
    1
      Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedGenericParameter.java
  18. 0
    1
      Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedVariant.java
  19. 1
    1
      Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedCallArguments.java
  20. 35
    35
      Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpression.java
  21. 2
    2
      Parser/src/main/java/org/openzen/zenscript/parser/member/ParsedDefinitionMember.java
  22. 23
    21
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatement.java
  23. 3
    2
      Parser/src/main/java/org/openzen/zenscript/parser/type/IParsedType.java

+ 34
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Library.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.constructor;
7
+
8
+import java.io.File;
9
+import org.json.JSONArray;
10
+import org.json.JSONObject;
11
+import org.openzen.zenscript.constructor.module.DirectoryModuleLoader;
12
+import org.openzen.zenscript.constructor.module.ModuleReference;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class Library {
19
+	public final String name;
20
+	public final File directory;
21
+	public final ModuleReference[] modules;
22
+	
23
+	public Library(ModuleLoader loader, File directory, String name, JSONObject json) {
24
+		this.name = name;
25
+		this.directory = new File(directory, json.getString("directory"));
26
+		
27
+		JSONArray modulesJson = json.getJSONArray("modules");
28
+		modules = new ModuleReference[modulesJson.length()];
29
+		for (int i = 0; i < modulesJson.length(); i++) {
30
+			String moduleName = modulesJson.getString(i);
31
+			modules[i] = new DirectoryModuleLoader(loader, moduleName, new File(this.directory, moduleName), false);
32
+		}
33
+	}
34
+}

+ 4
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Main.java View File

22
 		moduleLoader.register("stdlib", new DirectoryModuleLoader(moduleLoader, "stdlib", new File("libraries/stdlib"), true));
22
 		moduleLoader.register("stdlib", new DirectoryModuleLoader(moduleLoader, "stdlib", new File("libraries/stdlib"), true));
23
 		
23
 		
24
 		Project project = new Project(moduleLoader, currentDirectory);
24
 		Project project = new Project(moduleLoader, currentDirectory);
25
+		for (Library library : project.libraries) {
26
+			for (ModuleReference module : library.modules)
27
+				moduleLoader.register(module.getName(), module);
28
+		}
25
 		for (ModuleReference module : project.modules) {
29
 		for (ModuleReference module : project.modules) {
26
 			moduleLoader.register(module.getName(), module);
30
 			moduleLoader.register(module.getName(), module);
27
 		}
31
 		}

+ 12
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java View File

17
  * @author Hoofdgebruiker
17
  * @author Hoofdgebruiker
18
  */
18
  */
19
 public class Project {
19
 public class Project {
20
+	public final String name;
20
 	public final ModuleReference[] modules;
21
 	public final ModuleReference[] modules;
22
+	public final Library[] libraries;
21
 	
23
 	
22
 	public Project(ModuleLoader loader, File directory) throws IOException {
24
 	public Project(ModuleLoader loader, File directory) throws IOException {
25
+		name = directory.getName();
26
+		
23
 		if (!directory.exists())
27
 		if (!directory.exists())
24
 			throw new ConstructorException("Project directory doesn't exist");
28
 			throw new ConstructorException("Project directory doesn't exist");
25
 		if (!directory.isDirectory())
29
 		if (!directory.isDirectory())
31
 		
35
 		
32
 		JSONObject json = JSONUtils.load(projectFile);
36
 		JSONObject json = JSONUtils.load(projectFile);
33
 		
37
 		
38
+		JSONObject jsonLibraries = json.getJSONObject("libraries");
39
+		libraries = new Library[jsonLibraries.length()];
40
+		int k = 0;
41
+		for (String key : jsonLibraries.keySet()) {
42
+			libraries[k] = new Library(loader, directory, key, jsonLibraries.getJSONObject(key));
43
+			k++;
44
+		}
45
+		
34
 		JSONArray jsonModules = json.getJSONArray("modules");
46
 		JSONArray jsonModules = json.getJSONArray("modules");
35
 		modules = new ModuleReference[jsonModules.length()];
47
 		modules = new ModuleReference[jsonModules.length()];
36
 		for (int i = 0; i < jsonModules.length(); i++) {
48
 		for (int i = 0; i < jsonModules.length(); i++) {

+ 23
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java View File

28
 	private final String moduleName;
28
 	private final String moduleName;
29
 	private final File directory;
29
 	private final File directory;
30
 	private final boolean isStdlib;
30
 	private final boolean isStdlib;
31
+	private SourcePackage rootPackage = null;
31
 	
32
 	
32
 	public DirectoryModuleLoader(ModuleLoader loader, String moduleName, File directory, boolean isStdlib) {
33
 	public DirectoryModuleLoader(ModuleLoader loader, String moduleName, File directory, boolean isStdlib) {
33
 		this.loader = loader;
34
 		this.loader = loader;
93
 			throw new ConstructorException("Loading module files failed: " + ex.getMessage(), ex);
94
 			throw new ConstructorException("Loading module files failed: " + ex.getMessage(), ex);
94
 		}
95
 		}
95
 	}
96
 	}
97
+	
98
+	@Override
99
+	public SourcePackage getRootPackage() {
100
+		if (rootPackage == null)
101
+			rootPackage = loadPackage("", new File(directory, "src"));
102
+		
103
+		return rootPackage;
104
+	}
105
+	
106
+	private SourcePackage loadPackage(String name, File directory) {
107
+		SourcePackage pkg = new SourcePackage(name);
108
+		
109
+		for (File file : directory.listFiles()) {
110
+			if (file.isDirectory()) {
111
+				pkg.addPackage(loadPackage(file.getName(), file));
112
+			} else if (file.isFile() && file.getName().toLowerCase().endsWith(".zs")) {
113
+				pkg.addFile(new SourceFile(file.getName(), file));
114
+			}
115
+		}
116
+		
117
+		return pkg;
118
+	}
96
 }
119
 }

+ 2
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/ModuleReference.java View File

13
 	public String getName();
13
 	public String getName();
14
 	
14
 	
15
 	public SemanticModule load();
15
 	public SemanticModule load();
16
+	
17
+	public SourcePackage getRootPackage();
16
 }
18
 }

+ 22
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourceFile.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.constructor.module;
7
+
8
+import java.io.File;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class SourceFile {
15
+	public final String name;
16
+	public final File file;
17
+	
18
+	public SourceFile(String name, File file) {
19
+		this.name = name;
20
+		this.file = file;
21
+	}
22
+}

+ 31
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourcePackage.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.constructor.module;
7
+
8
+import java.util.HashMap;
9
+import java.util.Map;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class SourcePackage {
16
+	public final String name;
17
+	public final Map<String, SourcePackage> subPackages = new HashMap<>();
18
+	public final Map<String, SourceFile> sourceFiles = new HashMap<>();
19
+	
20
+	public SourcePackage(String name) {
21
+		this.name = name;
22
+	}
23
+	
24
+	public void addPackage(SourcePackage pkg) {
25
+		subPackages.put(pkg.name, pkg);
26
+	}
27
+	
28
+	public void addFile(SourceFile file) {
29
+		sourceFiles.put(file.name, file);
30
+	}
31
+}

+ 0
- 4
Parser/src/main/java/org/openzen/zenscript/lexer/Token.java View File

1
 /* Licensed under GPLv3 - https://opensource.org/licenses/GPL-3.0 */
1
 /* Licensed under GPLv3 - https://opensource.org/licenses/GPL-3.0 */
2
 package org.openzen.zenscript.lexer;
2
 package org.openzen.zenscript.lexer;
3
 
3
 
4
-import org.openzen.zenscript.shared.CodePosition;
5
-
6
 /**
4
 /**
7
  * Represents a token.
5
  * Represents a token.
8
  * 
6
  * 
11
  */
9
  */
12
 public interface Token<TT extends TokenType>
10
 public interface Token<TT extends TokenType>
13
 {
11
 {
14
-	CodePosition getPosition();
15
-	
16
 	TT getType();
12
 	TT getType();
17
 	
13
 	
18
 	String getContent();
14
 	String getContent();

+ 411
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/TokenParser.java View File

1
+/* Licensed under GPLv3 - https://opensource.org/licenses/GPL-3.0 */
2
+package org.openzen.zenscript.lexer;
3
+
4
+import java.io.IOException;
5
+import java.io.Reader;
6
+import java.io.StringReader;
7
+import java.util.Iterator;
8
+import java.util.LinkedList;
9
+import java.util.Stack;
10
+import org.openzen.zenscript.shared.CodePosition;
11
+
12
+/**
13
+ * Represents a token stream. A token stream reads characters from a reader and
14
+ * presents it as a series of tokens. Can be used to implement LL(*) parsers.
15
+ *
16
+ * Token classes with a negative class are considered to be whitespace.
17
+ *
18
+ * @author Stan Hebben
19
+ * @param <T> token class
20
+ * @param <TT> token type class
21
+ */
22
+public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> implements Iterator<T>
23
+{
24
+	private final String filename;
25
+    private final CountingReader reader;
26
+    private final CompiledDFA<TT> dfa;
27
+    private final LinkedList<PositionedToken> tokenMemory;
28
+    private final Stack<Integer> marks;
29
+	private final TT eof;
30
+	private final int tabSize = 4;
31
+	
32
+    private PositionedToken next;
33
+	
34
+    private int nextChar;
35
+    private int line;
36
+    private int lineOffset;
37
+	
38
+    private int tokenMemoryOffset;
39
+    private int tokenMemoryCurrent;
40
+    
41
+    /**
42
+     * Creates a token stream using the specified reader and DFA.
43
+     *
44
+	 * @param filename filename
45
+     * @param reader reader to read characters from
46
+     * @param dfa DFA to tokenize the stream
47
+	 * @param eof end of file token type
48
+     */
49
+    public TokenParser(String filename, Reader reader, CompiledDFA<TT> dfa, TT eof)
50
+	{
51
+		if (eof.isWhitespace()) // important for the advance() method
52
+			throw new IllegalArgumentException("EOF cannot be whitespace");
53
+		
54
+        tokenMemoryOffset = 0;
55
+        tokenMemoryCurrent = 0;
56
+        tokenMemory = new LinkedList<>();
57
+        marks = new Stack<>();
58
+        
59
+        this.reader = new CountingReader(reader);
60
+        this.dfa = dfa;
61
+		this.filename = filename;
62
+		this.eof = eof;
63
+		
64
+		try {
65
+	        nextChar = this.reader.read();
66
+		} catch (IOException ex) {
67
+			ioException(ex);
68
+		}
69
+		
70
+        line = 1;
71
+        lineOffset = 1;
72
+        advance();
73
+    }
74
+
75
+    /**
76
+     * Creates a token stream which reads data from the specified string.
77
+     *
78
+	 * @param filename filename
79
+     * @param data data to read
80
+     * @param dfa DFA to tokenize the stream
81
+	 * @param eof end of file token type
82
+     */
83
+    public TokenParser(String filename, String data, CompiledDFA<TT> dfa, TT eof)
84
+	{
85
+        this(filename, new StringReader(data), dfa, eof);
86
+    }
87
+	
88
+	public String getFilename()
89
+	{
90
+		return filename;
91
+	}
92
+	
93
+	public int getLine()
94
+	{
95
+		return line;
96
+	}
97
+	
98
+	public int getLineOffset()
99
+	{
100
+		return lineOffset;
101
+	}
102
+    
103
+    public T peek()
104
+	{
105
+        if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
106
+            return tokenMemory.get((tokenMemoryCurrent) - tokenMemoryOffset).token;
107
+        } else {
108
+            return next.token;
109
+        }
110
+    }
111
+
112
+    public boolean isNext(TT type)
113
+	{
114
+        return peek().getType() == type;
115
+    }
116
+
117
+    public T optional(TT type)
118
+	{
119
+        if (peek().getType() == type) {
120
+            return next();
121
+        } else {
122
+            return null;
123
+        }
124
+    }
125
+
126
+    public T required(TT type, String error)
127
+	{
128
+		T t = peek();
129
+        if (t.getType() == type) {
130
+            return next();
131
+        } else {
132
+			requiredTokenNotFound(getPosition(), error, t);
133
+			return null;
134
+        }
135
+    }
136
+	
137
+	public CodePosition getPosition()
138
+	{
139
+		if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
140
+            return tokenMemory.get((tokenMemoryCurrent) - tokenMemoryOffset).position;
141
+        } else {
142
+            return next.position;
143
+        }
144
+	}
145
+	
146
+	// =====================
147
+    // === LL(*) ability ===
148
+	// =====================
149
+
150
+    /**
151
+     * Pushes a mark on the mark stack.
152
+     */
153
+    public void pushMark()
154
+	{
155
+        marks.push(tokenMemoryCurrent);
156
+    }
157
+
158
+    /**
159
+     * Pops a mark from the mark stack without reset.
160
+     */
161
+    public void popMark()
162
+	{
163
+        marks.pop();
164
+
165
+        if (marks.isEmpty()) {
166
+            tokenMemoryOffset = tokenMemoryCurrent;
167
+            tokenMemory.clear();
168
+        }
169
+    }
170
+
171
+    /**
172
+     * Pops a mark from the mark stack and resets the stream's position to it
173
+     */
174
+    public void reset()
175
+	{
176
+        tokenMemoryCurrent = marks.pop();
177
+    }
178
+	
179
+	/**
180
+	 * Replaces the current token with another one. Used to split composite tokens.
181
+	 * 
182
+	 * @param other 
183
+	 */
184
+	public void replace(TT other) {
185
+		next = new PositionedToken(
186
+				next.position,
187
+				createToken(
188
+						next.token.getWhitespaceBefore(),
189
+						next.token.getContent(),
190
+						other));
191
+	}
192
+
193
+    // ===============================
194
+    // === Iterator implementation ===
195
+    // ===============================
196
+
197
+	@Override
198
+    public boolean hasNext()
199
+	{
200
+        return next.token.getType() != eof;
201
+    }
202
+
203
+	@Override
204
+    public T next()
205
+	{
206
+        if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
207
+            return tokenMemory.get((tokenMemoryCurrent++) - tokenMemoryOffset).token;
208
+        } else {
209
+            PositionedToken result = next;
210
+
211
+            if (marks.isEmpty()) {
212
+                tokenMemoryOffset++;
213
+            } else {
214
+                tokenMemory.add(result);
215
+            }
216
+            tokenMemoryCurrent++;
217
+
218
+            advance();
219
+            return result.token;
220
+        }
221
+    }
222
+
223
+	@Override
224
+    public void remove()
225
+	{
226
+        throw new UnsupportedOperationException("Not supported.");
227
+    }
228
+
229
+    // ==================================
230
+    // === Protected abstract methods ===
231
+    // ==================================
232
+	
233
+	/**
234
+	 * Called to create a token. May also be used to postprocess tokens while
235
+	 * generating them.
236
+	 * 
237
+	 * @param position token position (range)
238
+	 * @param value token value
239
+	 * @param tokenType token type
240
+	 * @return newly created token
241
+	 */
242
+	protected abstract T createToken(
243
+			String whitespaceBefore,
244
+			String value,
245
+			TT tokenType);
246
+	
247
+	/**
248
+	 * Called when a required token could not be found. Should log an error or
249
+	 * throw an exception. If no exception is thrown, the calling required
250
+	 * method will return null as token value.
251
+	 * 
252
+	 * @param position erroring position
253
+	 * @param error error to be logged
254
+	 * @param token incorrect token
255
+	 */
256
+	protected abstract void requiredTokenNotFound(
257
+			CodePosition position,
258
+			String error,
259
+			T token);
260
+	
261
+	/**
262
+	 * Called when the input contains an invalid token. Should either create
263
+	 * a token indicating an invalid token, or throw an exception.
264
+	 * 
265
+	 * @param position erroring position
266
+	 * @param token token value
267
+	 * @return a token marking an invalid token
268
+	 */
269
+	protected abstract T invalidToken(
270
+			String whitespaceBefore,
271
+			String token);
272
+	
273
+	/**
274
+	 * Called when an IO exception occurs. Should throw an exception of some
275
+	 * kind.
276
+	 * 
277
+	 * @param ex exception to be logged
278
+	 */
279
+	protected abstract void ioException(IOException ex);
280
+	
281
+    // =======================
282
+    // === Private methods ===
283
+    // =======================
284
+
285
+    /**
286
+     * Advances to the next non - whitespace token.
287
+     */
288
+    private void advance()
289
+	{
290
+		StringBuilder whitespace = new StringBuilder();
291
+        while (true) {
292
+            advanceToken(whitespace.toString());
293
+			if (next.token.getType().isWhitespace()) {
294
+				whitespace.append(next.token.getContent());
295
+			} else {
296
+				break;
297
+			}
298
+        }
299
+    }
300
+
301
+    /**
302
+     * Advances to the next token.
303
+     */
304
+    private void advanceToken(String whitespace)
305
+	{
306
+        if (nextChar < 0) {
307
+			CodePosition position = new CodePosition(
308
+					filename,
309
+					line,
310
+					lineOffset,
311
+					line,
312
+					lineOffset);
313
+			
314
+            next = new PositionedToken(position, createToken(whitespace, "", eof));
315
+            return;
316
+        }
317
+		
318
+        try {
319
+            int state = 0;
320
+            StringBuilder value = new StringBuilder();
321
+            int fromLine = line;
322
+            int fromLineOffset = lineOffset;
323
+            while (dfa.transitions[state].containsKey(nextChar)) {
324
+                value.append((char)nextChar);
325
+                state = dfa.transitions[state].get(nextChar);
326
+                line = reader.line;
327
+                lineOffset = reader.lineOffset;
328
+                nextChar = reader.read();
329
+            }
330
+			
331
+			if (line < 0)
332
+				throw new IllegalStateException("Line cannot be negative");
333
+			
334
+			CodePosition position = new CodePosition(filename, fromLine, fromLineOffset, line, lineOffset);
335
+            if (dfa.finals[state] != null) {
336
+                if (state == 0) {
337
+					value.append((char) nextChar);
338
+					next = new PositionedToken(position, invalidToken(
339
+							whitespace,
340
+							value.toString()));
341
+					nextChar = reader.read();
342
+				}
343
+				
344
+				next = new PositionedToken(position, createToken(
345
+						whitespace,
346
+						value.toString(), dfa.finals[state]));
347
+            } else {
348
+				if (nextChar < 0 && value.length() == 0)
349
+					return; // happens on comments at the end of files
350
+				
351
+				value.append((char) nextChar);
352
+				next = new PositionedToken(position, invalidToken(
353
+						whitespace,
354
+						value.toString()));
355
+				nextChar = reader.read();
356
+            }
357
+        } catch (IOException ex) {
358
+            ioException(ex);
359
+        }
360
+    }
361
+
362
+    // =============================
363
+    // === Private inner classes ===
364
+    // =============================
365
+
366
+    /**
367
+     * Keeps a line and line offset count.
368
+     */
369
+    private class CountingReader
370
+	{
371
+        private int line;
372
+        private int lineOffset;
373
+        private Reader reader;
374
+        private boolean eof;
375
+
376
+        public CountingReader(Reader reader)
377
+		{
378
+            this.reader = reader;
379
+            line = 1;
380
+            lineOffset = 1;
381
+        }
382
+
383
+        public int read() throws IOException
384
+		{
385
+            int ch = reader.read();
386
+            if (ch == -1) {
387
+                eof = true;
388
+                return ch;
389
+            }
390
+            if (ch == '\n') {
391
+                line++;
392
+                lineOffset = 1;
393
+            } else if (ch == '\t') {
394
+				lineOffset += tabSize;
395
+			} else {
396
+                lineOffset++;
397
+            }
398
+            return ch;
399
+        }
400
+    }
401
+	
402
+	private class PositionedToken {
403
+		public final CodePosition position;
404
+		public final T token;
405
+		
406
+		public PositionedToken(CodePosition position, T token) {
407
+			this.position = position;
408
+			this.token = token;
409
+		}
410
+	}
411
+}

+ 18
- 374
Parser/src/main/java/org/openzen/zenscript/lexer/TokenStream.java View File

1
-/* Licensed under GPLv3 - https://opensource.org/licenses/GPL-3.0 */
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
2
 package org.openzen.zenscript.lexer;
6
 package org.openzen.zenscript.lexer;
3
 
7
 
4
-import java.io.IOException;
5
-import java.io.Reader;
6
-import java.io.StringReader;
7
-import java.util.Iterator;
8
-import java.util.LinkedList;
9
-import java.util.Stack;
10
 import org.openzen.zenscript.shared.CodePosition;
8
 import org.openzen.zenscript.shared.CodePosition;
11
 
9
 
12
 /**
10
 /**
13
- * Represents a token stream. A token stream reads characters from a reader and
14
- * presents it as a series of tokens. Can be used to implement LL(*) parsers.
15
- *
16
- * Token classes with a negative class are considered to be whitespace.
17
  *
11
  *
18
- * @author Stan Hebben
19
- * @param <T> token class
20
- * @param <TT> token type class
12
+ * @author Hoofdgebruiker
21
  */
13
  */
22
-public abstract class TokenStream<T extends Token<TT>, TT extends TokenType> implements Iterator<T>
23
-{
24
-	private final String filename;
25
-    private final CountingReader reader;
26
-    private final CompiledDFA<TT> dfa;
27
-    private final LinkedList<T> tokenMemory;
28
-    private final Stack<Integer> marks;
29
-	private final TT eof;
30
-	private final int tabSize = 4;
14
+public interface TokenStream<TT extends TokenType, T extends Token<TT>> {
15
+	T peek();
31
 	
16
 	
32
-    private T next;
33
-    private int nextChar;
34
-    private int line;
35
-    private int lineOffset;
36
-	
37
-    private int tokenMemoryOffset;
38
-    private int tokenMemoryCurrent;
39
-    
40
-    /**
41
-     * Creates a token stream using the specified reader and DFA.
42
-     *
43
-	 * @param filename filename
44
-     * @param reader reader to read characters from
45
-     * @param dfa DFA to tokenize the stream
46
-	 * @param eof end of file token type
47
-     */
48
-    public TokenStream(String filename, Reader reader, CompiledDFA<TT> dfa, TT eof)
49
-	{
50
-		if (eof.isWhitespace()) // important for the advance() method
51
-			throw new IllegalArgumentException("EOF cannot be whitespace");
52
-		
53
-        tokenMemoryOffset = 0;
54
-        tokenMemoryCurrent = 0;
55
-        tokenMemory = new LinkedList<>();
56
-        marks = new Stack<>();
57
-        
58
-        this.reader = new CountingReader(reader);
59
-        this.dfa = dfa;
60
-		this.filename = filename;
61
-		this.eof = eof;
62
-		
63
-		try {
64
-	        nextChar = this.reader.read();
65
-		} catch (IOException ex) {
66
-			ioException(ex);
67
-		}
68
-		
69
-        line = 1;
70
-        lineOffset = 1;
71
-        advance();
72
-    }
73
-
74
-    /**
75
-     * Creates a token stream which reads data from the specified string.
76
-     *
77
-	 * @param filename filename
78
-     * @param data data to read
79
-     * @param dfa DFA to tokenize the stream
80
-	 * @param eof end of file token type
81
-     */
82
-    public TokenStream(String filename, String data, CompiledDFA<TT> dfa, TT eof)
83
-	{
84
-        this(filename, new StringReader(data), dfa, eof);
85
-    }
17
+	boolean isNext(TT type);
86
 	
18
 	
87
-	public String getFile()
88
-	{
89
-		return filename;
90
-	}
19
+	T optional(TT type);
91
 	
20
 	
92
-	public int getLine()
93
-	{
94
-		return line;
95
-	}
21
+	T required(TT type, String error);
96
 	
22
 	
97
-	public int getLineOffset()
98
-	{
99
-		return lineOffset;
100
-	}
101
-    
102
-    public T peek()
103
-	{
104
-        if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
105
-            return tokenMemory.get((tokenMemoryCurrent) - tokenMemoryOffset);
106
-        } else {
107
-            return next;
108
-        }
109
-    }
110
-
111
-    public boolean isNext(TT type)
112
-	{
113
-        return peek().getType() == type;
114
-    }
115
-
116
-    public T optional(TT type)
117
-	{
118
-        if (peek().getType() == type) {
119
-            return next();
120
-        } else {
121
-            return null;
122
-        }
123
-    }
124
-
125
-    public T required(TT type, String error)
126
-	{
127
-		T t = peek();
128
-        if (t.getType() == type) {
129
-            return next();
130
-        } else {
131
-			requiredTokenNotFound(getPosition(), error, t);
132
-			return null;
133
-        }
134
-    }
135
-	
136
-	public CodePosition getPosition()
137
-	{
138
-		return peek().getPosition();
139
-	}
140
-	
141
-	// =====================
142
-    // === LL(*) ability ===
143
-	// =====================
144
-
145
-    /**
146
-     * Pushes a mark on the mark stack.
147
-     */
148
-    public void pushMark()
149
-	{
150
-        marks.push(tokenMemoryCurrent);
151
-    }
152
-
153
-    /**
154
-     * Pops a mark from the mark stack without reset.
155
-     */
156
-    public void popMark()
157
-	{
158
-        marks.pop();
159
-
160
-        if (marks.isEmpty()) {
161
-            tokenMemoryOffset = tokenMemoryCurrent;
162
-            tokenMemory.clear();
163
-        }
164
-    }
165
-
166
-    /**
167
-     * Pops a mark from the mark stack and resets the stream's position to it
168
-     */
169
-    public void reset()
170
-	{
171
-        tokenMemoryCurrent = marks.pop();
172
-    }
23
+	void pushMark();
173
 	
24
 	
174
-	/**
175
-	 * Replaces the current token with another one. Used to split composite tokens.
176
-	 * 
177
-	 * @param other 
178
-	 */
179
-	public void replace(TT other) {
180
-		next = createToken(next.getPosition(), next.getWhitespaceBefore(), next.getContent(), other);
181
-	}
182
-
183
-    // ===============================
184
-    // === Iterator implementation ===
185
-    // ===============================
186
-
187
-	@Override
188
-    public boolean hasNext()
189
-	{
190
-        return next.getType() != eof;
191
-    }
192
-
193
-	@Override
194
-    public T next()
195
-	{
196
-        if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
197
-            return tokenMemory.get((tokenMemoryCurrent++) - tokenMemoryOffset);
198
-        } else {
199
-            T result = next;
200
-
201
-            if (marks.isEmpty()) {
202
-                tokenMemoryOffset++;
203
-            } else {
204
-                tokenMemory.add(result);
205
-            }
206
-            tokenMemoryCurrent++;
207
-
208
-            advance();
209
-            return result;
210
-        }
211
-    }
212
-
213
-	@Override
214
-    public void remove()
215
-	{
216
-        throw new UnsupportedOperationException("Not supported.");
217
-    }
218
-
219
-    // ==================================
220
-    // === Protected abstract methods ===
221
-    // ==================================
25
+	void popMark();
222
 	
26
 	
223
-	/**
224
-	 * Called to create a token. May also be used to postprocess tokens while
225
-	 * generating them.
226
-	 * 
227
-	 * @param position token position (range)
228
-	 * @param value token value
229
-	 * @param tokenType token type
230
-	 * @return newly created token
231
-	 */
232
-	protected abstract T createToken(
233
-			CodePosition position,
234
-			String whitespaceBefore,
235
-			String value,
236
-			TT tokenType);
27
+	void reset();
237
 	
28
 	
238
-	/**
239
-	 * Called when a required token could not be found. Should log an error or
240
-	 * throw an exception. If no exception is thrown, the calling required
241
-	 * method will return null as token value.
242
-	 * 
243
-	 * @param position erroring position
244
-	 * @param error error to be logged
245
-	 * @param token incorrect token
246
-	 */
247
-	protected abstract void requiredTokenNotFound(
248
-			CodePosition position,
249
-			String error,
250
-			T token);
29
+	void replace(TT other);
251
 	
30
 	
252
-	/**
253
-	 * Called when the input contains an invalid token. Should either create
254
-	 * a token indicating an invalid token, or throw an exception.
255
-	 * 
256
-	 * @param position erroring position
257
-	 * @param token token value
258
-	 * @return a token marking an invalid token
259
-	 */
260
-	protected abstract T invalidToken(
261
-			CodePosition position,
262
-			String whitespaceBefore,
263
-			String token);
31
+	boolean hasNext();
264
 	
32
 	
265
-	/**
266
-	 * Called when an IO exception occurs. Should throw an exception of some
267
-	 * kind.
268
-	 * 
269
-	 * @param ex exception to be logged
270
-	 */
271
-	protected abstract void ioException(IOException ex);
33
+	T next();
272
 	
34
 	
273
-    // =======================
274
-    // === Private methods ===
275
-    // =======================
276
-
277
-    /**
278
-     * Advances to the next non - whitespace token.
279
-     */
280
-    private void advance()
281
-	{
282
-		StringBuilder whitespace = new StringBuilder();
283
-        while (true) {
284
-            advanceToken(whitespace.toString());
285
-			if (next.getType().isWhitespace()) {
286
-				whitespace.append(next.getContent());
287
-			} else {
288
-				break;
289
-			}
290
-        }
291
-    }
292
-
293
-    /**
294
-     * Advances to the next token.
295
-     */
296
-    private void advanceToken(String whitespace)
297
-	{
298
-        if (nextChar < 0) {
299
-			CodePosition position = new CodePosition(
300
-					filename,
301
-					line,
302
-					lineOffset,
303
-					line,
304
-					lineOffset);
305
-			
306
-            next = createToken(position, whitespace, "", eof);
307
-            return;
308
-        }
309
-		
310
-        try {
311
-            int state = 0;
312
-            StringBuilder value = new StringBuilder();
313
-            int fromLine = line;
314
-            int fromLineOffset = lineOffset;
315
-            while (dfa.transitions[state].containsKey(nextChar)) {
316
-                value.append((char)nextChar);
317
-                state = dfa.transitions[state].get(nextChar);
318
-                line = reader.line;
319
-                lineOffset = reader.lineOffset;
320
-                nextChar = reader.read();
321
-            }
322
-			
323
-			if (line < 0)
324
-				throw new IllegalStateException("Line cannot be negative");
325
-			
326
-            if (dfa.finals[state] != null) {
327
-                if (state == 0) {
328
-					value.append((char) nextChar);
329
-					next = invalidToken(new CodePosition(filename, fromLine, fromLineOffset, line, lineOffset),
330
-							whitespace,
331
-							value.toString());
332
-					nextChar = reader.read();
333
-				}
334
-				
335
-				next = createToken(new CodePosition(filename, fromLine, fromLineOffset, line, lineOffset),
336
-						whitespace,
337
-						value.toString(), dfa.finals[state]);
338
-            } else {
339
-				if (nextChar < 0 && value.length() == 0)
340
-					return; // happens on comments at the end of files
341
-				
342
-				value.append((char) nextChar);
343
-				next = invalidToken(new CodePosition(filename, fromLine, fromLineOffset, line, lineOffset),
344
-						whitespace,
345
-						value.toString());
346
-				nextChar = reader.read();
347
-            }
348
-        } catch (IOException ex) {
349
-            ioException(ex);
350
-        }
351
-    }
352
-
353
-    // =============================
354
-    // === Private inner classes ===
355
-    // =============================
356
-
357
-    /**
358
-     * Keeps a line and line offset count.
359
-     */
360
-    private class CountingReader
361
-	{
362
-        private int line;
363
-        private int lineOffset;
364
-        private Reader reader;
365
-        private boolean eof;
366
-
367
-        public CountingReader(Reader reader)
368
-		{
369
-            this.reader = reader;
370
-            line = 1;
371
-            lineOffset = 1;
372
-        }
373
-
374
-        public int read() throws IOException
375
-		{
376
-            int ch = reader.read();
377
-            if (ch == -1) {
378
-                eof = true;
379
-                return ch;
380
-            }
381
-            if (ch == '\n') {
382
-                line++;
383
-                lineOffset = 1;
384
-            } else if (ch == '\t') {
385
-				lineOffset += tabSize;
386
-			} else {
387
-                lineOffset++;
388
-            }
389
-            return ch;
390
-        }
391
-    }
35
+	CodePosition getPosition();
392
 }
36
 }

+ 1
- 10
Parser/src/main/java/org/openzen/zenscript/lexer/ZSToken.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.lexer;
6
 package org.openzen.zenscript.lexer;
7
 
7
 
8
-import org.openzen.zenscript.shared.CodePosition;
9
-
10
 /**
8
 /**
11
  *
9
  *
12
  * @author Hoofdgebruiker
10
  * @author Hoofdgebruiker
13
  */
11
  */
14
 public class ZSToken implements Token<ZSTokenType> {
12
 public class ZSToken implements Token<ZSTokenType> {
15
-	public final CodePosition position;
16
 	public final ZSTokenType type;
13
 	public final ZSTokenType type;
17
 	public final String content;
14
 	public final String content;
18
 	public final String whitespaceBefore;
15
 	public final String whitespaceBefore;
19
 	
16
 	
20
-	public ZSToken(CodePosition position, ZSTokenType type, String content, String whitespaceBefore) {
21
-		this.position = position;
17
+	public ZSToken(ZSTokenType type, String content, String whitespaceBefore) {
22
 		this.type = type;
18
 		this.type = type;
23
 		this.content = content;
19
 		this.content = content;
24
 		this.whitespaceBefore = whitespaceBefore;
20
 		this.whitespaceBefore = whitespaceBefore;
25
 	}
21
 	}
26
-	
27
-	@Override
28
-	public CodePosition getPosition() {
29
-		return position;
30
-	}
31
 
22
 
32
 	@Override
23
 	@Override
33
 	public ZSTokenType getType() {
24
 	public ZSTokenType getType() {

+ 176
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenParser.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.lexer;
7
+
8
+import java.io.IOException;
9
+import java.io.Reader;
10
+import java.util.HashMap;
11
+import java.util.Map;
12
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
13
+import org.openzen.zenscript.shared.CompileException;
14
+import org.openzen.zenscript.shared.CompileExceptionCode;
15
+import static org.openzen.zenscript.lexer.ZSTokenType.*;
16
+import org.openzen.zenscript.shared.CodePosition;
17
+
18
+/**
19
+ *
20
+ * @author Hoofdgebruiker
21
+ */
22
+public class ZSTokenParser extends TokenParser<ZSToken, ZSTokenType> implements ZSTokenStream {
23
+	private static final CompiledDFA DFA = CompiledDFA.createLexerDFA(ZSTokenType.values(), ZSTokenType.class);
24
+	private static final Map<String, ZSTokenType> KEYWORDS = new HashMap<>();
25
+	
26
+	static {
27
+		KEYWORDS.put("import", K_IMPORT);
28
+		KEYWORDS.put("alias", K_ALIAS);
29
+		KEYWORDS.put("class", K_CLASS);
30
+		KEYWORDS.put("interface", K_INTERFACE);
31
+		KEYWORDS.put("enum", K_ENUM);
32
+		KEYWORDS.put("struct", K_STRUCT);
33
+		KEYWORDS.put("expand", K_EXPAND);
34
+		KEYWORDS.put("function", K_FUNCTION);
35
+		KEYWORDS.put("variant", K_VARIANT);
36
+		
37
+		KEYWORDS.put("abstract", K_ABSTRACT);
38
+		KEYWORDS.put("final", K_FINAL);
39
+		KEYWORDS.put("override", K_OVERRIDE);
40
+		KEYWORDS.put("const", K_CONST);
41
+		KEYWORDS.put("private", K_PRIVATE);
42
+		KEYWORDS.put("public", K_PUBLIC);
43
+		KEYWORDS.put("export", K_EXPORT);
44
+		KEYWORDS.put("static", K_STATIC);
45
+		KEYWORDS.put("protected", K_PROTECTED);
46
+		KEYWORDS.put("implicit", K_IMPLICIT);
47
+		KEYWORDS.put("virtual", K_VIRTUAL);
48
+		KEYWORDS.put("extern", K_EXTERN);
49
+		
50
+		KEYWORDS.put("val", K_VAL);
51
+		KEYWORDS.put("var", K_VAR);
52
+		KEYWORDS.put("get", K_GET);
53
+		KEYWORDS.put("implements", K_IMPLEMENTS);
54
+		KEYWORDS.put("set", K_SET);
55
+		
56
+		KEYWORDS.put("void", K_VOID);
57
+		KEYWORDS.put("any", K_ANY);
58
+		KEYWORDS.put("bool", K_BOOL);
59
+		KEYWORDS.put("byte", K_BYTE);
60
+		KEYWORDS.put("sbyte", K_SBYTE);
61
+		KEYWORDS.put("short", K_SHORT);
62
+		KEYWORDS.put("ushort", K_USHORT);
63
+		KEYWORDS.put("int", K_INT);
64
+		KEYWORDS.put("uint", K_UINT);
65
+		KEYWORDS.put("long", K_LONG);
66
+		KEYWORDS.put("ulong", K_ULONG);
67
+		KEYWORDS.put("float", K_FLOAT);
68
+		KEYWORDS.put("double", K_DOUBLE);
69
+		KEYWORDS.put("char", K_CHAR);
70
+		KEYWORDS.put("string", K_STRING);
71
+		
72
+		KEYWORDS.put("if", K_IF);
73
+		KEYWORDS.put("else", K_ELSE);
74
+		KEYWORDS.put("do", K_DO);
75
+		KEYWORDS.put("while", K_WHILE);
76
+		KEYWORDS.put("for", K_FOR);
77
+		KEYWORDS.put("throw", K_THROW);
78
+		KEYWORDS.put("lock", K_LOCK);
79
+		KEYWORDS.put("try", K_TRY);
80
+		KEYWORDS.put("catch", K_CATCH);
81
+		KEYWORDS.put("finally", K_FINALLY);
82
+		KEYWORDS.put("return", K_RETURN);
83
+		KEYWORDS.put("break", K_BREAK);
84
+		KEYWORDS.put("continue", K_CONTINUE);
85
+		KEYWORDS.put("switch", K_SWITCH);
86
+		KEYWORDS.put("case", K_CASE);
87
+		KEYWORDS.put("default", K_DEFAULT);
88
+		
89
+		KEYWORDS.put("in", K_IN);
90
+		KEYWORDS.put("is", K_IS);
91
+		KEYWORDS.put("as", K_AS);
92
+		KEYWORDS.put("match", K_MATCH);
93
+		KEYWORDS.put("throws", K_THROWS);
94
+		
95
+		KEYWORDS.put("this", K_THIS);
96
+		KEYWORDS.put("super", K_SUPER);
97
+		KEYWORDS.put("null", K_NULL);
98
+		KEYWORDS.put("true", K_TRUE);
99
+		KEYWORDS.put("false", K_FALSE);
100
+		KEYWORDS.put("new", K_NEW);
101
+	}
102
+	
103
+	private String whitespaceBuffer = null;
104
+	
105
+	public ZSTokenParser(String filename, Reader reader) {
106
+		super(filename, reader, DFA, ZSTokenType.EOF);
107
+	}
108
+	
109
+	@Override
110
+	public String loadWhitespace() {
111
+		if (whitespaceBuffer == null)
112
+			whitespaceBuffer = peek().whitespaceBefore;
113
+		
114
+		return whitespaceBuffer;
115
+	}
116
+	
117
+	@Override
118
+	public void reloadWhitespace() {
119
+		whitespaceBuffer = peek().whitespaceBefore;
120
+	}
121
+	
122
+	@Override
123
+	public String grabWhitespace() {
124
+		String result = loadWhitespace();
125
+		whitespaceBuffer = null;
126
+		return result;
127
+	}
128
+	
129
+	public String grabWhitespaceLine() {
130
+		String whitespace = loadWhitespace();
131
+		if (whitespace.contains("\n")) {
132
+			int index = whitespace.indexOf('\n');
133
+			whitespaceBuffer = whitespace.substring(index + 1);
134
+			return whitespace.substring(0, index);
135
+		} else {
136
+			whitespaceBuffer = "";
137
+			return whitespace;
138
+		}
139
+	}
140
+	
141
+	@Override
142
+	public void skipWhitespaceNewline() {
143
+		loadWhitespace();
144
+		int index = whitespaceBuffer.indexOf('\n');
145
+		if (index >= 0)
146
+			whitespaceBuffer = whitespaceBuffer.substring(index + 1);
147
+	}
148
+	
149
+	@Override
150
+	public WhitespaceInfo collectWhitespaceInfo(String whitespace, boolean skipLineBefore) {
151
+		return WhitespaceInfo.from(whitespace, grabWhitespaceLine(), skipLineBefore);
152
+	}
153
+	
154
+	@Override
155
+	protected ZSToken createToken(String whitespaceBefore, String value, ZSTokenType tokenType) {
156
+		if (tokenType == T_IDENTIFIER && KEYWORDS.containsKey(value))
157
+			tokenType = KEYWORDS.get(value);
158
+		
159
+		return new ZSToken(tokenType, value, whitespaceBefore);
160
+	}
161
+
162
+	@Override
163
+	protected void requiredTokenNotFound(CodePosition position, String error, ZSToken token) {
164
+		throw new CompileException(position, CompileExceptionCode.UNEXPECTED_TOKEN, error);
165
+	}
166
+
167
+	@Override
168
+	protected ZSToken invalidToken(String whitespaceBefore, String token) {
169
+		return new ZSToken(ZSTokenType.INVALID, token, whitespaceBefore);
170
+	}
171
+
172
+	@Override
173
+	protected void ioException(IOException ex) {
174
+		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
175
+	}
176
+}

+ 7
- 156
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenStream.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.lexer;
6
 package org.openzen.zenscript.lexer;
7
 
7
 
8
-import java.io.IOException;
9
-import java.io.Reader;
10
-import java.util.HashMap;
11
-import java.util.Map;
12
 import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.WhitespaceInfo;
13
-import org.openzen.zenscript.shared.CompileException;
14
-import org.openzen.zenscript.shared.CompileExceptionCode;
15
-import static org.openzen.zenscript.lexer.ZSTokenType.*;
16
-import org.openzen.zenscript.shared.CodePosition;
17
 
9
 
18
 /**
10
 /**
19
  *
11
  *
20
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
21
  */
13
  */
22
-public class ZSTokenStream extends TokenStream<ZSToken, ZSTokenType> {
23
-	private static final CompiledDFA DFA = CompiledDFA.createLexerDFA(ZSTokenType.values(), ZSTokenType.class);
24
-	private static final Map<String, ZSTokenType> KEYWORDS = new HashMap<>();
14
+public interface ZSTokenStream extends TokenStream<ZSTokenType, ZSToken> {
15
+	String getFilename();
25
 	
16
 	
26
-	static {
27
-		KEYWORDS.put("import", K_IMPORT);
28
-		KEYWORDS.put("alias", K_ALIAS);
29
-		KEYWORDS.put("class", K_CLASS);
30
-		KEYWORDS.put("interface", K_INTERFACE);
31
-		KEYWORDS.put("enum", K_ENUM);
32
-		KEYWORDS.put("struct", K_STRUCT);
33
-		KEYWORDS.put("expand", K_EXPAND);
34
-		KEYWORDS.put("function", K_FUNCTION);
35
-		KEYWORDS.put("variant", K_VARIANT);
36
-		
37
-		KEYWORDS.put("abstract", K_ABSTRACT);
38
-		KEYWORDS.put("final", K_FINAL);
39
-		KEYWORDS.put("override", K_OVERRIDE);
40
-		KEYWORDS.put("const", K_CONST);
41
-		KEYWORDS.put("private", K_PRIVATE);
42
-		KEYWORDS.put("public", K_PUBLIC);
43
-		KEYWORDS.put("export", K_EXPORT);
44
-		KEYWORDS.put("static", K_STATIC);
45
-		KEYWORDS.put("protected", K_PROTECTED);
46
-		KEYWORDS.put("implicit", K_IMPLICIT);
47
-		KEYWORDS.put("virtual", K_VIRTUAL);
48
-		KEYWORDS.put("extern", K_EXTERN);
49
-		
50
-		KEYWORDS.put("val", K_VAL);
51
-		KEYWORDS.put("var", K_VAR);
52
-		KEYWORDS.put("get", K_GET);
53
-		KEYWORDS.put("implements", K_IMPLEMENTS);
54
-		KEYWORDS.put("set", K_SET);
55
-		
56
-		KEYWORDS.put("void", K_VOID);
57
-		KEYWORDS.put("any", K_ANY);
58
-		KEYWORDS.put("bool", K_BOOL);
59
-		KEYWORDS.put("byte", K_BYTE);
60
-		KEYWORDS.put("sbyte", K_SBYTE);
61
-		KEYWORDS.put("short", K_SHORT);
62
-		KEYWORDS.put("ushort", K_USHORT);
63
-		KEYWORDS.put("int", K_INT);
64
-		KEYWORDS.put("uint", K_UINT);
65
-		KEYWORDS.put("long", K_LONG);
66
-		KEYWORDS.put("ulong", K_ULONG);
67
-		KEYWORDS.put("float", K_FLOAT);
68
-		KEYWORDS.put("double", K_DOUBLE);
69
-		KEYWORDS.put("char", K_CHAR);
70
-		KEYWORDS.put("string", K_STRING);
71
-		
72
-		KEYWORDS.put("if", K_IF);
73
-		KEYWORDS.put("else", K_ELSE);
74
-		KEYWORDS.put("do", K_DO);
75
-		KEYWORDS.put("while", K_WHILE);
76
-		KEYWORDS.put("for", K_FOR);
77
-		KEYWORDS.put("throw", K_THROW);
78
-		KEYWORDS.put("lock", K_LOCK);
79
-		KEYWORDS.put("try", K_TRY);
80
-		KEYWORDS.put("catch", K_CATCH);
81
-		KEYWORDS.put("finally", K_FINALLY);
82
-		KEYWORDS.put("return", K_RETURN);
83
-		KEYWORDS.put("break", K_BREAK);
84
-		KEYWORDS.put("continue", K_CONTINUE);
85
-		KEYWORDS.put("switch", K_SWITCH);
86
-		KEYWORDS.put("case", K_CASE);
87
-		KEYWORDS.put("default", K_DEFAULT);
88
-		
89
-		KEYWORDS.put("in", K_IN);
90
-		KEYWORDS.put("is", K_IS);
91
-		KEYWORDS.put("as", K_AS);
92
-		KEYWORDS.put("match", K_MATCH);
93
-		KEYWORDS.put("throws", K_THROWS);
94
-		
95
-		KEYWORDS.put("this", K_THIS);
96
-		KEYWORDS.put("super", K_SUPER);
97
-		KEYWORDS.put("null", K_NULL);
98
-		KEYWORDS.put("true", K_TRUE);
99
-		KEYWORDS.put("false", K_FALSE);
100
-		KEYWORDS.put("new", K_NEW);
101
-	}
17
+	String loadWhitespace();
102
 	
18
 	
103
-	private String whitespaceBuffer = null;
19
+	void reloadWhitespace();
104
 	
20
 	
105
-	public ZSTokenStream(String filename, Reader reader) {
106
-		super(filename, reader, DFA, ZSTokenType.EOF);
107
-	}
21
+	String grabWhitespace();
108
 	
22
 	
109
-	public String loadWhitespace() {
110
-		if (whitespaceBuffer == null)
111
-			whitespaceBuffer = peek().whitespaceBefore;
112
-		
113
-		return whitespaceBuffer;
114
-	}
23
+	void skipWhitespaceNewline();
115
 	
24
 	
116
-	public void reloadWhitespace() {
117
-		whitespaceBuffer = peek().whitespaceBefore;
118
-	}
119
-	
120
-	public String grabWhitespace() {
121
-		String result = loadWhitespace();
122
-		whitespaceBuffer = null;
123
-		return result;
124
-	}
125
-	
126
-	public String grabWhitespaceLine() {
127
-		String whitespace = loadWhitespace();
128
-		if (whitespace.contains("\n")) {
129
-			int index = whitespace.indexOf('\n');
130
-			whitespaceBuffer = whitespace.substring(index + 1);
131
-			return whitespace.substring(0, index);
132
-		} else {
133
-			whitespaceBuffer = "";
134
-			return whitespace;
135
-		}
136
-	}
137
-	
138
-	public void skipWhitespaceNewline() {
139
-		loadWhitespace();
140
-		int index = whitespaceBuffer.indexOf('\n');
141
-		if (index >= 0)
142
-			whitespaceBuffer = whitespaceBuffer.substring(index + 1);
143
-	}
144
-	
145
-	public WhitespaceInfo collectWhitespaceInfoForBlock(String whitespace) {
146
-		return WhitespaceInfo.from(whitespace, "", false);
147
-	}
148
-	
149
-	public WhitespaceInfo collectWhitespaceInfo(String whitespace, boolean skipLineBefore) {
150
-		return WhitespaceInfo.from(whitespace, grabWhitespaceLine(), skipLineBefore);
151
-	}
152
-	
153
-	@Override
154
-	protected ZSToken createToken(CodePosition position, String whitespaceBefore, String value, ZSTokenType tokenType) {
155
-		if (tokenType == T_IDENTIFIER && KEYWORDS.containsKey(value))
156
-			tokenType = KEYWORDS.get(value);
157
-		
158
-		return new ZSToken(position, tokenType, value, whitespaceBefore);
159
-	}
160
-
161
-	@Override
162
-	protected void requiredTokenNotFound(CodePosition position, String error, ZSToken token) {
163
-		throw new CompileException(position, CompileExceptionCode.UNEXPECTED_TOKEN, error);
164
-	}
165
-
166
-	@Override
167
-	protected ZSToken invalidToken(CodePosition position, String whitespaceBefore, String token) {
168
-		return new ZSToken(position, ZSTokenType.INVALID, token, whitespaceBefore);
169
-	}
170
-
171
-	@Override
172
-	protected void ioException(IOException ex) {
173
-		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
174
-	}
25
+	WhitespaceInfo collectWhitespaceInfo(String whitespace, boolean skipLineBefore);
175
 }
26
 }

+ 0
- 5
Parser/src/main/java/org/openzen/zenscript/parser/ParseException.java View File

6
 package org.openzen.zenscript.parser;
6
 package org.openzen.zenscript.parser;
7
 
7
 
8
 import org.openzen.zenscript.shared.CodePosition;
8
 import org.openzen.zenscript.shared.CodePosition;
9
-import org.openzen.zenscript.lexer.ZSToken;
10
 
9
 
11
 /**
10
 /**
12
  *
11
  *
13
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
14
  */
13
  */
15
 public class ParseException extends RuntimeException {
14
 public class ParseException extends RuntimeException {
16
-	public ParseException(ZSToken token, String message) {
17
-		this(token.position, message);
18
-	}
19
-	
20
 	public ParseException(CodePosition position, String message) {
15
 	public ParseException(CodePosition position, String message) {
21
 		super(position.toString() + ": " + message);
16
 		super(position.toString() + ": " + message);
22
 	}
17
 	}

+ 8
- 4
Parser/src/main/java/org/openzen/zenscript/parser/ParsedFile.java View File

27
 import org.openzen.zenscript.shared.CodePosition;
27
 import org.openzen.zenscript.shared.CodePosition;
28
 import org.openzen.zenscript.shared.CompileException;
28
 import org.openzen.zenscript.shared.CompileException;
29
 import org.openzen.zenscript.shared.CompileExceptionCode;
29
 import org.openzen.zenscript.shared.CompileExceptionCode;
30
+import org.openzen.zenscript.lexer.ZSTokenParser;
30
 import org.openzen.zenscript.lexer.ZSTokenStream;
31
 import org.openzen.zenscript.lexer.ZSTokenStream;
31
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
32
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
32
 import org.openzen.zenscript.linker.FileScope;
33
 import org.openzen.zenscript.linker.FileScope;
57
 	}
58
 	}
58
 	
59
 	
59
 	public static ParsedFile parse(ZSPackage pkg, String filename, Reader reader) throws IOException {
60
 	public static ParsedFile parse(ZSPackage pkg, String filename, Reader reader) throws IOException {
60
-		ParsedFile result = new ParsedFile(filename);
61
-		
62
-		ZSTokenStream tokens = new ZSTokenStream(filename, reader);
61
+		ZSTokenParser tokens = new ZSTokenParser(filename, reader);
62
+		return parse(pkg, tokens);
63
+	}
64
+	
65
+	public static ParsedFile parse(ZSPackage pkg, ZSTokenStream tokens) {
66
+		ParsedFile result = new ParsedFile(tokens.getFilename());
63
 		ZSToken eof = null;
67
 		ZSToken eof = null;
64
 
68
 
65
 		while (true) {
69
 		while (true) {
66
-			CodePosition position = tokens.peek().position;
70
+			CodePosition position = tokens.getPosition();
67
 			int modifiers = 0;
71
 			int modifiers = 0;
68
 			outer: while (true) {
72
 			outer: while (true) {
69
 				switch (tokens.peek().type) {
73
 				switch (tokens.peek().type) {

+ 2
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedEnumConstant.java View File

26
  */
26
  */
27
 public class ParsedEnumConstant {
27
 public class ParsedEnumConstant {
28
 	public static ParsedEnumConstant parse(ZSTokenStream tokens, EnumDefinition definition, int value) {
28
 	public static ParsedEnumConstant parse(ZSTokenStream tokens, EnumDefinition definition, int value) {
29
+		CodePosition position = tokens.getPosition();
29
 		ZSToken name = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected");
30
 		ZSToken name = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected");
30
 		List<ParsedExpression> arguments = new ArrayList<>();
31
 		List<ParsedExpression> arguments = new ArrayList<>();
31
 		if (tokens.optional(ZSTokenType.T_BROPEN) != null) {
32
 		if (tokens.optional(ZSTokenType.T_BROPEN) != null) {
35
 			tokens.required(ZSTokenType.T_BRCLOSE, ") expected");
36
 			tokens.required(ZSTokenType.T_BRCLOSE, ") expected");
36
 		}
37
 		}
37
 		
38
 		
38
-		return new ParsedEnumConstant(name.position, definition, name.content, value, arguments);
39
+		return new ParsedEnumConstant(position, definition, name.content, value, arguments);
39
 	}
40
 	}
40
 	
41
 	
41
 	public final CodePosition position;
42
 	public final CodePosition position;

+ 3
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedGenericParameter.java View File

9
 import java.util.List;
9
 import java.util.List;
10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
11
 import org.openzen.zenscript.lexer.ZSToken;
11
 import org.openzen.zenscript.lexer.ZSToken;
12
+import org.openzen.zenscript.lexer.ZSTokenParser;
12
 import org.openzen.zenscript.lexer.ZSTokenStream;
13
 import org.openzen.zenscript.lexer.ZSTokenStream;
13
 import org.openzen.zenscript.lexer.ZSTokenType;
14
 import org.openzen.zenscript.lexer.ZSTokenType;
14
 import org.openzen.zenscript.linker.BaseScope;
15
 import org.openzen.zenscript.linker.BaseScope;
22
  */
23
  */
23
 public class ParsedGenericParameter {
24
 public class ParsedGenericParameter {
24
 	public static ParsedGenericParameter parse(ZSTokenStream tokens) {
25
 	public static ParsedGenericParameter parse(ZSTokenStream tokens) {
26
+		CodePosition position = tokens.getPosition();
25
 		ZSToken name = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected");
27
 		ZSToken name = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected");
26
 		List<ParsedGenericBound> bounds = new ArrayList<>();
28
 		List<ParsedGenericBound> bounds = new ArrayList<>();
27
 		while (tokens.optional(ZSTokenType.T_COLON) != null) {
29
 		while (tokens.optional(ZSTokenType.T_COLON) != null) {
31
 				bounds.add(new ParsedTypeBound(tokens.getPosition(), IParsedType.parse(tokens)));
33
 				bounds.add(new ParsedTypeBound(tokens.getPosition(), IParsedType.parse(tokens)));
32
 			}
34
 			}
33
 		}
35
 		}
34
-		return new ParsedGenericParameter(name.position, name.content, bounds);
36
+		return new ParsedGenericParameter(position, name.content, bounds);
35
 	}
37
 	}
36
 	
38
 	
37
 	public static List<ParsedGenericParameter> parseAll(ZSTokenStream tokens) {
39
 	public static List<ParsedGenericParameter> parseAll(ZSTokenStream tokens) {

+ 0
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedVariant.java View File

10
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
10
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
11
 import org.openzen.zenscript.codemodel.definition.VariantDefinition;
11
 import org.openzen.zenscript.codemodel.definition.VariantDefinition;
12
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
12
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
13
-import org.openzen.zenscript.codemodel.scope.TypeScope;
14
 import org.openzen.zenscript.lexer.ZSTokenStream;
13
 import org.openzen.zenscript.lexer.ZSTokenStream;
15
 import org.openzen.zenscript.lexer.ZSTokenType;
14
 import org.openzen.zenscript.lexer.ZSTokenType;
16
 import org.openzen.zenscript.linker.BaseScope;
15
 import org.openzen.zenscript.linker.BaseScope;

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedCallArguments.java View File

9
 import java.util.Collections;
9
 import java.util.Collections;
10
 import java.util.List;
10
 import java.util.List;
11
 import java.util.stream.Collectors;
11
 import java.util.stream.Collectors;
12
-import org.openzen.zenscript.lexer.ZSTokenStream;
13
 import org.openzen.zenscript.lexer.ZSTokenType;
12
 import org.openzen.zenscript.lexer.ZSTokenType;
14
 import org.openzen.zenscript.codemodel.FunctionHeader;
13
 import org.openzen.zenscript.codemodel.FunctionHeader;
15
 import org.openzen.zenscript.codemodel.expression.CallArguments;
14
 import org.openzen.zenscript.codemodel.expression.CallArguments;
17
 import org.openzen.zenscript.codemodel.partial.IPartialExpression;
16
 import org.openzen.zenscript.codemodel.partial.IPartialExpression;
18
 import org.openzen.zenscript.codemodel.type.ITypeID;
17
 import org.openzen.zenscript.codemodel.type.ITypeID;
19
 import org.openzen.zenscript.codemodel.type.member.DefinitionMemberGroup;
18
 import org.openzen.zenscript.codemodel.type.member.DefinitionMemberGroup;
19
+import org.openzen.zenscript.lexer.ZSTokenStream;
20
 import org.openzen.zenscript.linker.BaseScope;
20
 import org.openzen.zenscript.linker.BaseScope;
21
 import org.openzen.zenscript.linker.ExpressionScope;
21
 import org.openzen.zenscript.linker.ExpressionScope;
22
 import org.openzen.zenscript.shared.CodePosition;
22
 import org.openzen.zenscript.shared.CodePosition;

+ 35
- 35
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpression.java View File

11
 import java.util.Collections;
11
 import java.util.Collections;
12
 import java.util.List;
12
 import java.util.List;
13
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
13
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
14
-import org.openzen.zenscript.lexer.ZSTokenStream;
15
 import org.openzen.zenscript.lexer.ZSTokenType;
14
 import org.openzen.zenscript.lexer.ZSTokenType;
16
 import org.openzen.zenscript.codemodel.CompareType;
15
 import org.openzen.zenscript.codemodel.CompareType;
17
 import org.openzen.zenscript.codemodel.OperatorType;
16
 import org.openzen.zenscript.codemodel.OperatorType;
20
 import org.openzen.zenscript.codemodel.partial.IPartialExpression;
19
 import org.openzen.zenscript.codemodel.partial.IPartialExpression;
21
 import org.openzen.zenscript.codemodel.type.ITypeID;
20
 import org.openzen.zenscript.codemodel.type.ITypeID;
22
 import org.openzen.zenscript.lexer.ZSToken;
21
 import org.openzen.zenscript.lexer.ZSToken;
22
+import org.openzen.zenscript.lexer.ZSTokenStream;
23
 import org.openzen.zenscript.linker.BaseScope;
23
 import org.openzen.zenscript.linker.BaseScope;
24
 import org.openzen.zenscript.parser.ParseException;
24
 import org.openzen.zenscript.parser.ParseException;
25
 import org.openzen.zenscript.parser.definitions.ParsedFunctionHeader;
25
 import org.openzen.zenscript.parser.definitions.ParsedFunctionHeader;
108
 		ParsedExpression left = readOrOrExpression(position, parser, options);
108
 		ParsedExpression left = readOrOrExpression(position, parser, options);
109
 
109
 
110
 		if (parser.optional(T_QUEST) != null) {
110
 		if (parser.optional(T_QUEST) != null) {
111
-			ParsedExpression onIf = readOrOrExpression(parser.peek().position, parser, options);
111
+			ParsedExpression onIf = readOrOrExpression(parser.getPosition(), parser, options);
112
 			parser.required(T_COLON, ": expected");
112
 			parser.required(T_COLON, ": expected");
113
-			ParsedExpression onElse = readConditionalExpression(parser.peek().position, parser, options);
113
+			ParsedExpression onElse = readConditionalExpression(parser.getPosition(), parser, options);
114
 			return new ParsedExpressionConditional(position, left, onIf, onElse);
114
 			return new ParsedExpressionConditional(position, left, onIf, onElse);
115
 		}
115
 		}
116
 
116
 
121
 		ParsedExpression left = readAndAndExpression(position, parser, options);
121
 		ParsedExpression left = readAndAndExpression(position, parser, options);
122
 
122
 
123
 		while (parser.optional(T_OROR) != null) {
123
 		while (parser.optional(T_OROR) != null) {
124
-			ParsedExpression right = readAndAndExpression(parser.peek().position, parser, options);
124
+			ParsedExpression right = readAndAndExpression(parser.getPosition(), parser, options);
125
 			left = new ParsedExpressionOrOr(position, left, right);
125
 			left = new ParsedExpressionOrOr(position, left, right);
126
 		}
126
 		}
127
 		
127
 		
128
 		while (parser.optional(T_COALESCE) != null) {
128
 		while (parser.optional(T_COALESCE) != null) {
129
-			ParsedExpression right = readAndAndExpression(parser.peek().position, parser, options);
129
+			ParsedExpression right = readAndAndExpression(parser.getPosition(), parser, options);
130
 			left = new ParsedExpressionCoalesce(position, left, right);
130
 			left = new ParsedExpressionCoalesce(position, left, right);
131
 		}
131
 		}
132
 		
132
 		
137
 		ParsedExpression left = readOrExpression(position, parser, options);
137
 		ParsedExpression left = readOrExpression(position, parser, options);
138
 
138
 
139
 		while (parser.optional(T_ANDAND) != null) {
139
 		while (parser.optional(T_ANDAND) != null) {
140
-			ParsedExpression right = readOrExpression(parser.peek().position, parser, options);
140
+			ParsedExpression right = readOrExpression(parser.getPosition(), parser, options);
141
 			left = new ParsedExpressionAndAnd(position, left, right);
141
 			left = new ParsedExpressionAndAnd(position, left, right);
142
 		}
142
 		}
143
 		return left;
143
 		return left;
147
 		ParsedExpression left = readXorExpression(position, parser, options);
147
 		ParsedExpression left = readXorExpression(position, parser, options);
148
 
148
 
149
 		while (parser.optional(T_OR) != null) {
149
 		while (parser.optional(T_OR) != null) {
150
-			ParsedExpression right = readXorExpression(parser.peek().position, parser, options);
150
+			ParsedExpression right = readXorExpression(parser.getPosition(), parser, options);
151
 			left = new ParsedExpressionBinary(position, left, right, OperatorType.OR);
151
 			left = new ParsedExpressionBinary(position, left, right, OperatorType.OR);
152
 		}
152
 		}
153
 		return left;
153
 		return left;
157
 		ParsedExpression left = readAndExpression(position, parser, options);
157
 		ParsedExpression left = readAndExpression(position, parser, options);
158
 
158
 
159
 		while (parser.optional(T_XOR) != null) {
159
 		while (parser.optional(T_XOR) != null) {
160
-			ParsedExpression right = readAndExpression(parser.peek().position, parser, options);
160
+			ParsedExpression right = readAndExpression(parser.getPosition(), parser, options);
161
 			left = new ParsedExpressionBinary(position, left, right, OperatorType.XOR);
161
 			left = new ParsedExpressionBinary(position, left, right, OperatorType.XOR);
162
 		}
162
 		}
163
 		return left;
163
 		return left;
167
 		ParsedExpression left = readCompareExpression(position, parser, options);
167
 		ParsedExpression left = readCompareExpression(position, parser, options);
168
 
168
 
169
 		while (parser.optional(T_AND) != null) {
169
 		while (parser.optional(T_AND) != null) {
170
-			ParsedExpression right = readCompareExpression(parser.peek().position, parser, options);
170
+			ParsedExpression right = readCompareExpression(parser.getPosition(), parser, options);
171
 			left = new ParsedExpressionBinary(position, left, right, OperatorType.AND);
171
 			left = new ParsedExpressionBinary(position, left, right, OperatorType.AND);
172
 		}
172
 		}
173
 		return left;
173
 		return left;
179
 		switch (parser.peek().getType()) {
179
 		switch (parser.peek().getType()) {
180
 			case T_EQUAL2: {
180
 			case T_EQUAL2: {
181
 				parser.next();
181
 				parser.next();
182
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
182
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
183
 				return new ParsedExpressionCompare(position, left, right, CompareType.EQ);
183
 				return new ParsedExpressionCompare(position, left, right, CompareType.EQ);
184
 			}
184
 			}
185
 			case T_EQUAL3: {
185
 			case T_EQUAL3: {
186
 				parser.next();
186
 				parser.next();
187
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
187
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
188
 				return new ParsedExpressionCompare(position, left, right, CompareType.SAME);
188
 				return new ParsedExpressionCompare(position, left, right, CompareType.SAME);
189
 			}
189
 			}
190
 			case T_NOTEQUAL: {
190
 			case T_NOTEQUAL: {
191
 				parser.next();
191
 				parser.next();
192
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
192
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
193
 				return new ParsedExpressionCompare(position, left, right, CompareType.NE);
193
 				return new ParsedExpressionCompare(position, left, right, CompareType.NE);
194
 			}
194
 			}
195
 			case T_NOTEQUAL2: {
195
 			case T_NOTEQUAL2: {
196
 				parser.next();
196
 				parser.next();
197
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
197
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
198
 				return new ParsedExpressionCompare(position, left, right, CompareType.NOTSAME);
198
 				return new ParsedExpressionCompare(position, left, right, CompareType.NOTSAME);
199
 			}
199
 			}
200
 			case T_LESS: {
200
 			case T_LESS: {
201
 				parser.next();
201
 				parser.next();
202
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
202
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
203
 				return new ParsedExpressionCompare(position, left, right, CompareType.LT);
203
 				return new ParsedExpressionCompare(position, left, right, CompareType.LT);
204
 			}
204
 			}
205
 			case T_LESSEQ: {
205
 			case T_LESSEQ: {
206
 				parser.next();
206
 				parser.next();
207
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
207
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
208
 				return new ParsedExpressionCompare(position, left, right, CompareType.LE);
208
 				return new ParsedExpressionCompare(position, left, right, CompareType.LE);
209
 			}
209
 			}
210
 			case T_GREATER: {
210
 			case T_GREATER: {
211
 				parser.next();
211
 				parser.next();
212
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
212
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
213
 				return new ParsedExpressionCompare(position, left, right, CompareType.GT);
213
 				return new ParsedExpressionCompare(position, left, right, CompareType.GT);
214
 			}
214
 			}
215
 			case T_GREATEREQ: {
215
 			case T_GREATEREQ: {
216
 				parser.next();
216
 				parser.next();
217
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
217
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
218
 				return new ParsedExpressionCompare(position, left, right, CompareType.GE);
218
 				return new ParsedExpressionCompare(position, left, right, CompareType.GE);
219
 			}
219
 			}
220
 			case K_IN: {
220
 			case K_IN: {
221
 				parser.next();
221
 				parser.next();
222
-				ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
222
+				ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
223
 				return new ParsedExpressionBinary(position, right, left, OperatorType.CONTAINS);
223
 				return new ParsedExpressionBinary(position, right, left, OperatorType.CONTAINS);
224
 			}
224
 			}
225
 			case K_IS: {
225
 			case K_IS: {
230
 			case T_NOT: {
230
 			case T_NOT: {
231
 				parser.next();
231
 				parser.next();
232
 				if (parser.optional(K_IN) != null) {
232
 				if (parser.optional(K_IN) != null) {
233
-					ParsedExpression right = readShiftExpression(parser.peek().position, parser, options);
233
+					ParsedExpression right = readShiftExpression(parser.getPosition(), parser, options);
234
 					return new ParsedExpressionUnary(position, new ParsedExpressionBinary(position, right, left, OperatorType.CONTAINS), OperatorType.NOT);
234
 					return new ParsedExpressionUnary(position, new ParsedExpressionBinary(position, right, left, OperatorType.CONTAINS), OperatorType.NOT);
235
 				} else if (parser.optional(K_IS) != null) {
235
 				} else if (parser.optional(K_IS) != null) {
236
 					IParsedType type = IParsedType.parse(parser);
236
 					IParsedType type = IParsedType.parse(parser);
249
 		
249
 		
250
 		while (true) {
250
 		while (true) {
251
 			if (parser.optional(T_SHL) != null) {
251
 			if (parser.optional(T_SHL) != null) {
252
-				ParsedExpression right = readAddExpression(parser.peek().position, parser, options);
252
+				ParsedExpression right = readAddExpression(parser.getPosition(), parser, options);
253
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.SHL);
253
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.SHL);
254
 			} else if (parser.optional(T_SHR) != null) {
254
 			} else if (parser.optional(T_SHR) != null) {
255
-				ParsedExpression right = readAddExpression(parser.peek().position, parser, options);
255
+				ParsedExpression right = readAddExpression(parser.getPosition(), parser, options);
256
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.SHR);
256
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.SHR);
257
 			} else if (parser.optional(T_USHR) != null) {
257
 			} else if (parser.optional(T_USHR) != null) {
258
-				ParsedExpression right = readAddExpression(parser.peek().position, parser, options);
258
+				ParsedExpression right = readAddExpression(parser.getPosition(), parser, options);
259
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.USHR);
259
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.USHR);
260
 			} else {
260
 			} else {
261
 				break;
261
 				break;
270
 		
270
 		
271
 		while (true) {
271
 		while (true) {
272
 			if (parser.optional(T_ADD) != null) {
272
 			if (parser.optional(T_ADD) != null) {
273
-				ParsedExpression right = readMulExpression(parser.peek().position, parser, options);
273
+				ParsedExpression right = readMulExpression(parser.getPosition(), parser, options);
274
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.ADD);
274
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.ADD);
275
 			} else if (parser.optional(T_SUB) != null) {
275
 			} else if (parser.optional(T_SUB) != null) {
276
-				ParsedExpression right = readMulExpression(parser.peek().position, parser, options);
276
+				ParsedExpression right = readMulExpression(parser.getPosition(), parser, options);
277
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.SUB);
277
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.SUB);
278
 			} else if (parser.optional(T_CAT) != null) {
278
 			} else if (parser.optional(T_CAT) != null) {
279
-				ParsedExpression right = readMulExpression(parser.peek().position, parser, options);
279
+				ParsedExpression right = readMulExpression(parser.getPosition(), parser, options);
280
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.CAT);
280
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.CAT);
281
 			} else {
281
 			} else {
282
 				break;
282
 				break;
290
 
290
 
291
 		while (true) {
291
 		while (true) {
292
 			if (parser.optional(T_MUL) != null) {
292
 			if (parser.optional(T_MUL) != null) {
293
-				ParsedExpression right = readUnaryExpression(parser.peek().position, parser, options);
293
+				ParsedExpression right = readUnaryExpression(parser.getPosition(), parser, options);
294
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.MUL);
294
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.MUL);
295
 			} else if (parser.optional(T_DIV) != null) {
295
 			} else if (parser.optional(T_DIV) != null) {
296
-				ParsedExpression right = readUnaryExpression(parser.peek().position, parser, options);
296
+				ParsedExpression right = readUnaryExpression(parser.getPosition(), parser, options);
297
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.DIV);
297
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.DIV);
298
 			} else if (parser.optional(T_MOD) != null) {
298
 			} else if (parser.optional(T_MOD) != null) {
299
-				ParsedExpression right = readUnaryExpression(parser.peek().position, parser, options);
299
+				ParsedExpression right = readUnaryExpression(parser.getPosition(), parser, options);
300
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.MOD);
300
 				left = new ParsedExpressionBinary(position, left, right, OperatorType.MOD);
301
 			} else {
301
 			} else {
302
 				break;
302
 				break;
312
 				parser.next();
312
 				parser.next();
313
 				return new ParsedExpressionUnary(
313
 				return new ParsedExpressionUnary(
314
 						position,
314
 						position,
315
-						readUnaryExpression(parser.peek().position, parser, options),
315
+						readUnaryExpression(parser.getPosition(), parser, options),
316
 						OperatorType.NOT);
316
 						OperatorType.NOT);
317
 			case T_SUB:
317
 			case T_SUB:
318
 				parser.next();
318
 				parser.next();
319
 				return new ParsedExpressionUnary(
319
 				return new ParsedExpressionUnary(
320
 						position,
320
 						position,
321
-						readUnaryExpression(parser.peek().position, parser, options),
321
+						readUnaryExpression(parser.getPosition(), parser, options),
322
 						OperatorType.NEG);
322
 						OperatorType.NEG);
323
 			case T_CAT:
323
 			case T_CAT:
324
 				parser.next();
324
 				parser.next();
325
 				return new ParsedExpressionUnary(
325
 				return new ParsedExpressionUnary(
326
 						position,
326
 						position,
327
-						readUnaryExpression(parser.peek().position, parser, options),
327
+						readUnaryExpression(parser.getPosition(), parser, options),
328
 						OperatorType.CAT);
328
 						OperatorType.CAT);
329
 			case T_INCREMENT:
329
 			case T_INCREMENT:
330
 				parser.next();
330
 				parser.next();
331
 				return new ParsedExpressionUnary(
331
 				return new ParsedExpressionUnary(
332
 						position,
332
 						position,
333
-						readUnaryExpression(parser.peek().position, parser, options),
333
+						readUnaryExpression(parser.getPosition(), parser, options),
334
 						OperatorType.INCREMENT);
334
 						OperatorType.INCREMENT);
335
 			case T_DECREMENT:
335
 			case T_DECREMENT:
336
 				parser.next();
336
 				parser.next();
337
 				return new ParsedExpressionUnary(
337
 				return new ParsedExpressionUnary(
338
 						position,
338
 						position,
339
-						readUnaryExpression(parser.peek().position, parser, options),
339
+						readUnaryExpression(parser.getPosition(), parser, options),
340
 						OperatorType.DECREMENT);
340
 						OperatorType.DECREMENT);
341
 			case K_TRY:
341
 			case K_TRY:
342
 				parser.next();
342
 				parser.next();
381
 						base = new ParsedExpressionMember(position, base, unescape(indexString2.content), Collections.emptyList());
381
 						base = new ParsedExpressionMember(position, base, unescape(indexString2.content), Collections.emptyList());
382
 					} else {
382
 					} else {
383
 						ZSToken last = parser.next();
383
 						ZSToken last = parser.next();
384
-						throw new ParseException(last, "Invalid expression, last token: " + last.content);
384
+						throw new ParseException(parser.getPosition(), "Invalid expression, last token: " + last.content);
385
 					}
385
 					}
386
 				}
386
 				}
387
 			} else if (parser.optional(T_DOT2) != null) {
387
 			} else if (parser.optional(T_DOT2) != null) {
532
 				IParsedType type = IParsedType.parse(parser);
532
 				IParsedType type = IParsedType.parse(parser);
533
 				if (type == null) {
533
 				if (type == null) {
534
 					ZSToken last = parser.next();
534
 					ZSToken last = parser.next();
535
-					throw new ParseException(last, "Invalid expression, last token: " + last.content);
535
+					throw new ParseException(parser.getPosition(), "Invalid expression, last token: " + last.content);
536
 				} else {
536
 				} else {
537
 					return new ParsedTypeExpression(position, type);
537
 					return new ParsedTypeExpression(position, type);
538
 				}
538
 				}

+ 2
- 2
Parser/src/main/java/org/openzen/zenscript/parser/member/ParsedDefinitionMember.java View File

265
 			default:
265
 			default:
266
 				if (modifiers == Modifiers.STATIC && tokens.peek().type == ZSTokenType.T_AOPEN) {
266
 				if (modifiers == Modifiers.STATIC && tokens.peek().type == ZSTokenType.T_AOPEN) {
267
 					ParsedStatementBlock body = ParsedStatementBlock.parseBlock(tokens, true);
267
 					ParsedStatementBlock body = ParsedStatementBlock.parseBlock(tokens, true);
268
-					return new ParsedStaticInitializer(forDefinition, tokens.peek().position, body);
268
+					return new ParsedStaticInitializer(forDefinition, tokens.getPosition(), body);
269
 				}
269
 				}
270
-				throw new CompileException(tokens.peek().position, CompileExceptionCode.UNEXPECTED_TOKEN, "Unexpected token: " + tokens.peek().content);
270
+				throw new CompileException(tokens.getPosition(), CompileExceptionCode.UNEXPECTED_TOKEN, "Unexpected token: " + tokens.peek().content);
271
 		}
271
 		}
272
 	}
272
 	}
273
 	
273
 	

+ 23
- 21
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatement.java View File

19
 
19
 
20
 public abstract class ParsedStatement {
20
 public abstract class ParsedStatement {
21
 	public static ParsedFunctionBody parseLambdaBody(ZSTokenStream tokens, boolean inExpression) {
21
 	public static ParsedFunctionBody parseLambdaBody(ZSTokenStream tokens, boolean inExpression) {
22
+		CodePosition position = tokens.getPosition();
22
 		ZSToken start = tokens.peek();
23
 		ZSToken start = tokens.peek();
23
 		if (tokens.optional(T_AOPEN) != null) {
24
 		if (tokens.optional(T_AOPEN) != null) {
24
 			List<ParsedStatement> statements = new ArrayList<>();
25
 			List<ParsedStatement> statements = new ArrayList<>();
25
 			while (tokens.optional(T_ACLOSE) == null)
26
 			while (tokens.optional(T_ACLOSE) == null)
26
 				statements.add(ParsedStatement.parse(tokens));
27
 				statements.add(ParsedStatement.parse(tokens));
27
 			
28
 			
28
-			return new ParsedStatementsFunctionBody(new ParsedStatementBlock(start.position, null, null, statements));
29
+			return new ParsedStatementsFunctionBody(new ParsedStatementBlock(position, null, null, statements));
29
 		} else {
30
 		} else {
30
 			ParsedFunctionBody result = new ParsedLambdaFunctionBody(ParsedExpression.parse(tokens));
31
 			ParsedFunctionBody result = new ParsedLambdaFunctionBody(ParsedExpression.parse(tokens));
31
 			if (!inExpression)
32
 			if (!inExpression)
45
 	
46
 	
46
 	public static ParsedStatementBlock parseBlock(ZSTokenStream parser, boolean isFirst) {
47
 	public static ParsedStatementBlock parseBlock(ZSTokenStream parser, boolean isFirst) {
47
 		String ws = parser.grabWhitespace();
48
 		String ws = parser.grabWhitespace();
48
-		ZSToken t = parser.required(T_AOPEN, "{ expected");
49
+		CodePosition position = parser.getPosition();
50
+		parser.required(T_AOPEN, "{ expected");
49
 
51
 
50
 		parser.reloadWhitespace();
52
 		parser.reloadWhitespace();
51
 		parser.skipWhitespaceNewline();
53
 		parser.skipWhitespaceNewline();
60
 
62
 
61
 		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
63
 		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
62
 		WhitespacePostComment postComment = WhitespacePostComment.fromWhitespace(last.whitespaceBefore);
64
 		WhitespacePostComment postComment = WhitespacePostComment.fromWhitespace(last.whitespaceBefore);
63
-		return new ParsedStatementBlock(t.getPosition(), whitespace, postComment, statements);
65
+		return new ParsedStatementBlock(position, whitespace, postComment, statements);
64
 	}
66
 	}
65
 	
67
 	
66
 	public static ParsedStatement parse(ZSTokenStream parser) {
68
 	public static ParsedStatement parse(ZSTokenStream parser) {
69
 	
71
 	
70
 	public static ParsedStatement parse(ZSTokenStream parser, boolean isFirst) {
72
 	public static ParsedStatement parse(ZSTokenStream parser, boolean isFirst) {
71
 		String ws = parser.grabWhitespace();
73
 		String ws = parser.grabWhitespace();
74
+		CodePosition position = parser.getPosition();
72
 		ZSToken next = parser.peek();
75
 		ZSToken next = parser.peek();
73
 		switch (next.getType()) {
76
 		switch (next.getType()) {
74
 			case T_AOPEN:
77
 			case T_AOPEN:
83
 				parser.required(T_SEMICOLON, "; expected");
86
 				parser.required(T_SEMICOLON, "; expected");
84
 				
87
 				
85
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
88
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
86
-				return new ParsedStatementReturn(next.getPosition(), whitespace, expression);
89
+				return new ParsedStatementReturn(position, whitespace, expression);
87
 			}
90
 			}
88
 			case K_VAR:
91
 			case K_VAR:
89
 			case K_VAL: {
92
 			case K_VAL: {
101
 				parser.required(T_SEMICOLON, "; expected");
104
 				parser.required(T_SEMICOLON, "; expected");
102
 				
105
 				
103
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
106
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
104
-				return new ParsedStatementVar(start.getPosition(), whitespace, name, type, initializer, start.getType() == K_VAL);
107
+				return new ParsedStatementVar(position, whitespace, name, type, initializer, start.getType() == K_VAL);
105
 			}
108
 			}
106
 			case K_IF: {
109
 			case K_IF: {
107
-				ZSToken t = parser.next();
110
+				parser.next();
108
 				ParsedExpression expression = ParsedExpression.parse(parser);
111
 				ParsedExpression expression = ParsedExpression.parse(parser);
109
 				parser.skipWhitespaceNewline();
112
 				parser.skipWhitespaceNewline();
110
 				ParsedStatement onIf = parse(parser);
113
 				ParsedStatement onIf = parse(parser);
116
 				}
119
 				}
117
 				
120
 				
118
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
121
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
119
-				return new ParsedStatementIf(t.getPosition(), whitespace, expression, onIf, onElse);
122
+				return new ParsedStatementIf(position, whitespace, expression, onIf, onElse);
120
 			}
123
 			}
121
 			case K_FOR: {
124
 			case K_FOR: {
122
-				ZSToken t = parser.next();
125
+				parser.next();
123
 				String name = parser.required(T_IDENTIFIER, "identifier expected").content;
126
 				String name = parser.required(T_IDENTIFIER, "identifier expected").content;
124
 				List<String> names = new ArrayList<>();
127
 				List<String> names = new ArrayList<>();
125
 				names.add(name);
128
 				names.add(name);
134
 				
137
 				
135
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
138
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
136
 				return new ParsedStatementForeach(
139
 				return new ParsedStatementForeach(
137
-						t.getPosition(),
140
+						position,
138
 						whitespace,
141
 						whitespace,
139
 						names.toArray(new String[names.size()]),
142
 						names.toArray(new String[names.size()]),
140
 						source,
143
 						source,
152
 				parser.required(T_SEMICOLON, "; expected");
155
 				parser.required(T_SEMICOLON, "; expected");
153
 				
156
 				
154
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
157
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
155
-				return new ParsedStatementDoWhile(t.position, whitespace, label, content, condition);
158
+				return new ParsedStatementDoWhile(position, whitespace, label, content, condition);
156
 			}
159
 			}
157
 			case K_WHILE: {
160
 			case K_WHILE: {
158
 				ZSToken t = parser.next();
161
 				ZSToken t = parser.next();
164
 				ParsedStatement content = parse(parser);
167
 				ParsedStatement content = parse(parser);
165
 				
168
 				
166
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
169
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
167
-				return new ParsedStatementWhile(t.position, whitespace, label, condition, content);
170
+				return new ParsedStatementWhile(position, whitespace, label, condition, content);
168
 			}
171
 			}
169
 			case K_LOCK: {
172
 			case K_LOCK: {
170
 				ZSToken t = parser.next();
173
 				ZSToken t = parser.next();
172
 				ParsedStatement content = parse(parser);
175
 				ParsedStatement content = parse(parser);
173
 				
176
 				
174
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
177
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
175
-				return new ParsedStatementLock(t.position, whitespace, object, content);
178
+				return new ParsedStatementLock(position, whitespace, object, content);
176
 			}
179
 			}
177
 			case K_THROW: {
180
 			case K_THROW: {
178
 				ZSToken t = parser.next();
181
 				ZSToken t = parser.next();
180
 				parser.required(T_SEMICOLON, "; expected");
183
 				parser.required(T_SEMICOLON, "; expected");
181
 				
184
 				
182
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
185
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
183
-				return new ParsedStatementThrow(t.position, whitespace, value);
186
+				return new ParsedStatementThrow(position, whitespace, value);
184
 			}
187
 			}
185
 			case K_TRY: {
188
 			case K_TRY: {
186
 				parser.pushMark();
189
 				parser.pushMark();
206
 				ParsedStatement content = parse(parser);
209
 				ParsedStatement content = parse(parser);
207
 				List<ParsedCatchClause> catchClauses = new ArrayList<>();
210
 				List<ParsedCatchClause> catchClauses = new ArrayList<>();
208
 				while (parser.optional(K_CATCH) != null) {
211
 				while (parser.optional(K_CATCH) != null) {
209
-					CodePosition position = parser.getPosition();
212
+					CodePosition catchPosition = parser.getPosition();
210
 					
213
 					
211
 					String catchName = null;
214
 					String catchName = null;
212
 					if (parser.isNext(ZSTokenType.T_IDENTIFIER))
215
 					if (parser.isNext(ZSTokenType.T_IDENTIFIER))
217
 						catchType = IParsedType.parse(parser);
220
 						catchType = IParsedType.parse(parser);
218
 					
221
 					
219
 					ParsedStatement catchContent = ParsedStatement.parse(parser);
222
 					ParsedStatement catchContent = ParsedStatement.parse(parser);
220
-					catchClauses.add(new ParsedCatchClause(position, catchName, catchType, catchContent));
223
+					catchClauses.add(new ParsedCatchClause(catchPosition, catchName, catchType, catchContent));
221
 				}
224
 				}
222
 				
225
 				
223
 				ParsedStatement finallyClause = null;
226
 				ParsedStatement finallyClause = null;
225
 					finallyClause = ParsedStatement.parse(parser);
228
 					finallyClause = ParsedStatement.parse(parser);
226
 				
229
 				
227
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
230
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
228
-				return new ParsedStatementTryCatch(t.position, whitespace, name, initializer, content, catchClauses, finallyClause);
231
+				return new ParsedStatementTryCatch(position, whitespace, name, initializer, content, catchClauses, finallyClause);
229
 			}
232
 			}
230
 			case K_CONTINUE: {
233
 			case K_CONTINUE: {
231
 				ZSToken t = parser.next();
234
 				ZSToken t = parser.next();
236
 				parser.required(T_SEMICOLON, "; expected");
239
 				parser.required(T_SEMICOLON, "; expected");
237
 				
240
 				
238
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
241
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
239
-				return new ParsedStatementContinue(t.position, whitespace, name);
242
+				return new ParsedStatementContinue(position, whitespace, name);
240
 			}
243
 			}
241
 			case K_BREAK: {
244
 			case K_BREAK: {
242
 				ZSToken t = parser.next();
245
 				ZSToken t = parser.next();
247
 				parser.required(T_SEMICOLON, "; expected");
250
 				parser.required(T_SEMICOLON, "; expected");
248
 				
251
 				
249
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
252
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
250
-				return new ParsedStatementBreak(t.position, whitespace, name);
253
+				return new ParsedStatementBreak(position, whitespace, name);
251
 			}
254
 			}
252
 			case K_SWITCH: {
255
 			case K_SWITCH: {
253
 				ZSToken t = parser.next();
256
 				ZSToken t = parser.next();
277
 				}
280
 				}
278
 				
281
 				
279
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
282
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
280
-				return new ParsedStatementSwitch(t.position, whitespace, name, value, cases);
283
+				return new ParsedStatementSwitch(position, whitespace, name, value, cases);
281
 			}
284
 			}
282
 		}
285
 		}
283
-
284
-		CodePosition position = parser.peek().getPosition();
286
+		
285
 		ParsedExpression expression = ParsedExpression.parse(parser);
287
 		ParsedExpression expression = ParsedExpression.parse(parser);
286
 		parser.required(T_SEMICOLON, "; expected");
288
 		parser.required(T_SEMICOLON, "; expected");
287
 		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
289
 		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);

+ 3
- 2
Parser/src/main/java/org/openzen/zenscript/parser/type/IParsedType.java View File

105
 				result = ParsedTypeBasic.STRING;
105
 				result = ParsedTypeBasic.STRING;
106
 				break;
106
 				break;
107
 			case K_FUNCTION: {
107
 			case K_FUNCTION: {
108
-				CodePosition position = tokens.next().position;
108
+				CodePosition position = tokens.getPosition();
109
+				tokens.next();
109
 				ParsedFunctionHeader header = ParsedFunctionHeader.parse(tokens);
110
 				ParsedFunctionHeader header = ParsedFunctionHeader.parse(tokens);
110
 				result = new ParsedFunctionType(position, header);
111
 				result = new ParsedFunctionType(position, header);
111
 				break;
112
 				break;
112
 			}
113
 			}
113
 			case T_IDENTIFIER: {
114
 			case T_IDENTIFIER: {
114
-				CodePosition position = tokens.peek().position;
115
+				CodePosition position = tokens.getPosition();
115
 				List<ParsedNamedType.ParsedNamePart> name = new ArrayList<>();
116
 				List<ParsedNamedType.ParsedNamePart> name = new ArrayList<>();
116
 				do {
117
 				do {
117
 					String namePart = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected").content;
118
 					String namePart = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected").content;

Loading…
Cancel
Save