Преглед на файлове

- 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 години
родител
ревизия
6feb3f4246
променени са 23 файла, в които са добавени 818 реда и са изтрити 617 реда
  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 Целия файл

@@ -0,0 +1,34 @@
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 Целия файл

@@ -22,6 +22,10 @@ public class Main {
22 22
 		moduleLoader.register("stdlib", new DirectoryModuleLoader(moduleLoader, "stdlib", new File("libraries/stdlib"), true));
23 23
 		
24 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 29
 		for (ModuleReference module : project.modules) {
26 30
 			moduleLoader.register(module.getName(), module);
27 31
 		}

+ 12
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java Целия файл

@@ -17,9 +17,13 @@ import org.openzen.zenscript.constructor.module.ModuleReference;
17 17
  * @author Hoofdgebruiker
18 18
  */
19 19
 public class Project {
20
+	public final String name;
20 21
 	public final ModuleReference[] modules;
22
+	public final Library[] libraries;
21 23
 	
22 24
 	public Project(ModuleLoader loader, File directory) throws IOException {
25
+		name = directory.getName();
26
+		
23 27
 		if (!directory.exists())
24 28
 			throw new ConstructorException("Project directory doesn't exist");
25 29
 		if (!directory.isDirectory())
@@ -31,6 +35,14 @@ public class Project {
31 35
 		
32 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 46
 		JSONArray jsonModules = json.getJSONArray("modules");
35 47
 		modules = new ModuleReference[jsonModules.length()];
36 48
 		for (int i = 0; i < jsonModules.length(); i++) {

+ 23
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java Целия файл

@@ -28,6 +28,7 @@ public class DirectoryModuleLoader implements ModuleReference {
28 28
 	private final String moduleName;
29 29
 	private final File directory;
30 30
 	private final boolean isStdlib;
31
+	private SourcePackage rootPackage = null;
31 32
 	
32 33
 	public DirectoryModuleLoader(ModuleLoader loader, String moduleName, File directory, boolean isStdlib) {
33 34
 		this.loader = loader;
@@ -93,4 +94,26 @@ public class DirectoryModuleLoader implements ModuleReference {
93 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 Целия файл

@@ -13,4 +13,6 @@ public interface ModuleReference {
13 13
 	public String getName();
14 14
 	
15 15
 	public SemanticModule load();
16
+	
17
+	public SourcePackage getRootPackage();
16 18
 }

+ 22
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourceFile.java Целия файл

@@ -0,0 +1,22 @@
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 Целия файл

@@ -0,0 +1,31 @@
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 Целия файл

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

+ 411
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/TokenParser.java Целия файл

@@ -0,0 +1,411 @@
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 Целия файл

@@ -1,392 +1,36 @@
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 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 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 Целия файл

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

+ 176
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenParser.java Целия файл

@@ -0,0 +1,176 @@
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 Целия файл

@@ -5,171 +5,22 @@
5 5
  */
6 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 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 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 Целия файл

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

+ 8
- 4
Parser/src/main/java/org/openzen/zenscript/parser/ParsedFile.java Целия файл

@@ -27,6 +27,7 @@ import org.openzen.zenscript.lexer.ZSToken;
27 27
 import org.openzen.zenscript.shared.CodePosition;
28 28
 import org.openzen.zenscript.shared.CompileException;
29 29
 import org.openzen.zenscript.shared.CompileExceptionCode;
30
+import org.openzen.zenscript.lexer.ZSTokenParser;
30 31
 import org.openzen.zenscript.lexer.ZSTokenStream;
31 32
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
32 33
 import org.openzen.zenscript.linker.FileScope;
@@ -57,13 +58,16 @@ public class ParsedFile {
57 58
 	}
58 59
 	
59 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 67
 		ZSToken eof = null;
64 68
 
65 69
 		while (true) {
66
-			CodePosition position = tokens.peek().position;
70
+			CodePosition position = tokens.getPosition();
67 71
 			int modifiers = 0;
68 72
 			outer: while (true) {
69 73
 				switch (tokens.peek().type) {

+ 2
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedEnumConstant.java Целия файл

@@ -26,6 +26,7 @@ import org.openzen.zenscript.shared.CodePosition;
26 26
  */
27 27
 public class ParsedEnumConstant {
28 28
 	public static ParsedEnumConstant parse(ZSTokenStream tokens, EnumDefinition definition, int value) {
29
+		CodePosition position = tokens.getPosition();
29 30
 		ZSToken name = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected");
30 31
 		List<ParsedExpression> arguments = new ArrayList<>();
31 32
 		if (tokens.optional(ZSTokenType.T_BROPEN) != null) {
@@ -35,7 +36,7 @@ public class ParsedEnumConstant {
35 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 42
 	public final CodePosition position;

+ 3
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedGenericParameter.java Целия файл

@@ -9,6 +9,7 @@ import java.util.ArrayList;
9 9
 import java.util.List;
10 10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
11 11
 import org.openzen.zenscript.lexer.ZSToken;
12
+import org.openzen.zenscript.lexer.ZSTokenParser;
12 13
 import org.openzen.zenscript.lexer.ZSTokenStream;
13 14
 import org.openzen.zenscript.lexer.ZSTokenType;
14 15
 import org.openzen.zenscript.linker.BaseScope;
@@ -22,6 +23,7 @@ import org.openzen.zenscript.shared.CodePosition;
22 23
  */
23 24
 public class ParsedGenericParameter {
24 25
 	public static ParsedGenericParameter parse(ZSTokenStream tokens) {
26
+		CodePosition position = tokens.getPosition();
25 27
 		ZSToken name = tokens.required(ZSTokenType.T_IDENTIFIER, "identifier expected");
26 28
 		List<ParsedGenericBound> bounds = new ArrayList<>();
27 29
 		while (tokens.optional(ZSTokenType.T_COLON) != null) {
@@ -31,7 +33,7 @@ public class ParsedGenericParameter {
31 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 39
 	public static List<ParsedGenericParameter> parseAll(ZSTokenStream tokens) {

+ 0
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedVariant.java Целия файл

@@ -10,7 +10,6 @@ import java.util.List;
10 10
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
11 11
 import org.openzen.zenscript.codemodel.definition.VariantDefinition;
12 12
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
13
-import org.openzen.zenscript.codemodel.scope.TypeScope;
14 13
 import org.openzen.zenscript.lexer.ZSTokenStream;
15 14
 import org.openzen.zenscript.lexer.ZSTokenType;
16 15
 import org.openzen.zenscript.linker.BaseScope;

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedCallArguments.java Целия файл

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

+ 35
- 35
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpression.java Целия файл

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

+ 2
- 2
Parser/src/main/java/org/openzen/zenscript/parser/member/ParsedDefinitionMember.java Целия файл

@@ -265,9 +265,9 @@ public abstract class ParsedDefinitionMember {
265 265
 			default:
266 266
 				if (modifiers == Modifiers.STATIC && tokens.peek().type == ZSTokenType.T_AOPEN) {
267 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 Целия файл

@@ -19,13 +19,14 @@ import org.openzen.zenscript.shared.CompileExceptionCode;
19 19
 
20 20
 public abstract class ParsedStatement {
21 21
 	public static ParsedFunctionBody parseLambdaBody(ZSTokenStream tokens, boolean inExpression) {
22
+		CodePosition position = tokens.getPosition();
22 23
 		ZSToken start = tokens.peek();
23 24
 		if (tokens.optional(T_AOPEN) != null) {
24 25
 			List<ParsedStatement> statements = new ArrayList<>();
25 26
 			while (tokens.optional(T_ACLOSE) == null)
26 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 30
 		} else {
30 31
 			ParsedFunctionBody result = new ParsedLambdaFunctionBody(ParsedExpression.parse(tokens));
31 32
 			if (!inExpression)
@@ -45,7 +46,8 @@ public abstract class ParsedStatement {
45 46
 	
46 47
 	public static ParsedStatementBlock parseBlock(ZSTokenStream parser, boolean isFirst) {
47 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 52
 		parser.reloadWhitespace();
51 53
 		parser.skipWhitespaceNewline();
@@ -60,7 +62,7 @@ public abstract class ParsedStatement {
60 62
 
61 63
 		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
62 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 68
 	public static ParsedStatement parse(ZSTokenStream parser) {
@@ -69,6 +71,7 @@ public abstract class ParsedStatement {
69 71
 	
70 72
 	public static ParsedStatement parse(ZSTokenStream parser, boolean isFirst) {
71 73
 		String ws = parser.grabWhitespace();
74
+		CodePosition position = parser.getPosition();
72 75
 		ZSToken next = parser.peek();
73 76
 		switch (next.getType()) {
74 77
 			case T_AOPEN:
@@ -83,7 +86,7 @@ public abstract class ParsedStatement {
83 86
 				parser.required(T_SEMICOLON, "; expected");
84 87
 				
85 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 91
 			case K_VAR:
89 92
 			case K_VAL: {
@@ -101,10 +104,10 @@ public abstract class ParsedStatement {
101 104
 				parser.required(T_SEMICOLON, "; expected");
102 105
 				
103 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 109
 			case K_IF: {
107
-				ZSToken t = parser.next();
110
+				parser.next();
108 111
 				ParsedExpression expression = ParsedExpression.parse(parser);
109 112
 				parser.skipWhitespaceNewline();
110 113
 				ParsedStatement onIf = parse(parser);
@@ -116,10 +119,10 @@ public abstract class ParsedStatement {
116 119
 				}
117 120
 				
118 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 124
 			case K_FOR: {
122
-				ZSToken t = parser.next();
125
+				parser.next();
123 126
 				String name = parser.required(T_IDENTIFIER, "identifier expected").content;
124 127
 				List<String> names = new ArrayList<>();
125 128
 				names.add(name);
@@ -134,7 +137,7 @@ public abstract class ParsedStatement {
134 137
 				
135 138
 				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);
136 139
 				return new ParsedStatementForeach(
137
-						t.getPosition(),
140
+						position,
138 141
 						whitespace,
139 142
 						names.toArray(new String[names.size()]),
140 143
 						source,
@@ -152,7 +155,7 @@ public abstract class ParsedStatement {
152 155
 				parser.required(T_SEMICOLON, "; expected");
153 156
 				
154 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 160
 			case K_WHILE: {
158 161
 				ZSToken t = parser.next();
@@ -164,7 +167,7 @@ public abstract class ParsedStatement {
164 167
 				ParsedStatement content = parse(parser);
165 168
 				
166 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 172
 			case K_LOCK: {
170 173
 				ZSToken t = parser.next();
@@ -172,7 +175,7 @@ public abstract class ParsedStatement {
172 175
 				ParsedStatement content = parse(parser);
173 176
 				
174 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 180
 			case K_THROW: {
178 181
 				ZSToken t = parser.next();
@@ -180,7 +183,7 @@ public abstract class ParsedStatement {
180 183
 				parser.required(T_SEMICOLON, "; expected");
181 184
 				
182 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 188
 			case K_TRY: {
186 189
 				parser.pushMark();
@@ -206,7 +209,7 @@ public abstract class ParsedStatement {
206 209
 				ParsedStatement content = parse(parser);
207 210
 				List<ParsedCatchClause> catchClauses = new ArrayList<>();
208 211
 				while (parser.optional(K_CATCH) != null) {
209
-					CodePosition position = parser.getPosition();
212
+					CodePosition catchPosition = parser.getPosition();
210 213
 					
211 214
 					String catchName = null;
212 215
 					if (parser.isNext(ZSTokenType.T_IDENTIFIER))
@@ -217,7 +220,7 @@ public abstract class ParsedStatement {
217 220
 						catchType = IParsedType.parse(parser);
218 221
 					
219 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 226
 				ParsedStatement finallyClause = null;
@@ -225,7 +228,7 @@ public abstract class ParsedStatement {
225 228
 					finallyClause = ParsedStatement.parse(parser);
226 229
 				
227 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 233
 			case K_CONTINUE: {
231 234
 				ZSToken t = parser.next();
@@ -236,7 +239,7 @@ public abstract class ParsedStatement {
236 239
 				parser.required(T_SEMICOLON, "; expected");
237 240
 				
238 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 244
 			case K_BREAK: {
242 245
 				ZSToken t = parser.next();
@@ -247,7 +250,7 @@ public abstract class ParsedStatement {
247 250
 				parser.required(T_SEMICOLON, "; expected");
248 251
 				
249 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 255
 			case K_SWITCH: {
253 256
 				ZSToken t = parser.next();
@@ -277,11 +280,10 @@ public abstract class ParsedStatement {
277 280
 				}
278 281
 				
279 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 287
 		ParsedExpression expression = ParsedExpression.parse(parser);
286 288
 		parser.required(T_SEMICOLON, "; expected");
287 289
 		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws, isFirst);

+ 3
- 2
Parser/src/main/java/org/openzen/zenscript/parser/type/IParsedType.java Целия файл

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

Loading…
Отказ
Запис