Browse Source

Separating parser responsibilities in multiple classes. (temporarily breaks whitespace preservation)

Stan Hebben 6 years ago
parent
commit
71be205a81

+ 19
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/MemoryTokenStream.java View File

@@ -0,0 +1,19 @@
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
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface MemoryTokenStream<TT extends TokenType, T extends Token<TT>>
13
+		extends TokenStream<TT, T> {
14
+	void pushMark();
15
+	
16
+	void popMark();
17
+	
18
+	void reset();
19
+}

+ 84
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/MemoryTokenStreamImpl.java View File

@@ -0,0 +1,84 @@
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.util.LinkedList;
9
+import java.util.Stack;
10
+import org.openzen.zenscript.shared.CodePosition;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public abstract class MemoryTokenStreamImpl<TT extends TokenType, T extends Token<TT>> implements TokenStream<TT, T> {
17
+	private final TokenStream<TT, T> stream;
18
+    private final LinkedList<TokenParser.PositionedToken<T>> tokenMemory = new LinkedList<>();
19
+    private final Stack<Integer> marks = new Stack<>();
20
+	
21
+    private int tokenMemoryOffset = 0;
22
+    private int tokenMemoryCurrent = 0;
23
+	
24
+	public MemoryTokenStreamImpl(TokenStream<TT, T> stream) {
25
+		this.stream = stream;
26
+	}
27
+	
28
+	public void pushMark() {
29
+        marks.push(tokenMemoryCurrent);
30
+	}
31
+	
32
+	public void popMark() {
33
+        marks.pop();
34
+
35
+        if (marks.isEmpty()) {
36
+            tokenMemoryOffset = tokenMemoryCurrent;
37
+            tokenMemory.clear();
38
+        }
39
+	}
40
+	
41
+	public void reset() {
42
+        tokenMemoryCurrent = marks.pop();
43
+	}
44
+
45
+	@Override
46
+	public T peek() {
47
+		if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
48
+            return tokenMemory.get((tokenMemoryCurrent) - tokenMemoryOffset).token;
49
+        } else {
50
+            return stream.peek();
51
+        }
52
+	}
53
+
54
+	@Override
55
+	public void replace(TT other) {
56
+		stream.replace(other);
57
+	}
58
+
59
+	@Override
60
+	public T next() {
61
+		if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
62
+            return tokenMemory.get((tokenMemoryCurrent++) - tokenMemoryOffset).token;
63
+        } else {
64
+            T result = stream.peek();
65
+            if (marks.isEmpty()) {
66
+                tokenMemoryOffset++;
67
+            } else {
68
+                tokenMemory.add(new TokenParser.PositionedToken<>(stream.getPosition(), stream.peek()));
69
+            }
70
+            tokenMemoryCurrent++;
71
+            stream.next();
72
+			return result;
73
+        }
74
+	}
75
+
76
+	@Override
77
+	public CodePosition getPosition() {
78
+		if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
79
+            return tokenMemory.get((tokenMemoryCurrent) - tokenMemoryOffset).position;
80
+        } else {
81
+            return stream.getPosition();
82
+        }
83
+	}
84
+}

+ 14
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/TokenFactory.java View File

@@ -0,0 +1,14 @@
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
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface TokenFactory<T, TT> {
13
+	T create(TT type, String content, String whitespaceBefore);
14
+}

+ 38
- 199
Parser/src/main/java/org/openzen/zenscript/lexer/TokenParser.java View File

@@ -4,10 +4,9 @@ package org.openzen.zenscript.lexer;
4 4
 import java.io.IOException;
5 5
 import java.io.Reader;
6 6
 import java.io.StringReader;
7
-import java.util.Iterator;
8
-import java.util.LinkedList;
9
-import java.util.Stack;
10 7
 import org.openzen.zenscript.shared.CodePosition;
8
+import org.openzen.zenscript.shared.CompileException;
9
+import org.openzen.zenscript.shared.CompileExceptionCode;
11 10
 
12 11
 /**
13 12
  * Represents a token stream. A token stream reads characters from a reader and
@@ -19,25 +18,22 @@ import org.openzen.zenscript.shared.CodePosition;
19 18
  * @param <T> token class
20 19
  * @param <TT> token type class
21 20
  */
22
-public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> implements Iterator<T>
21
+public class TokenParser<T extends Token<TT>, TT extends TokenType> implements TokenStream<TT, T>
23 22
 {
24 23
 	private final String filename;
25 24
     private final CountingReader reader;
26 25
     private final CompiledDFA<TT> dfa;
27
-    private final LinkedList<PositionedToken> tokenMemory;
28
-    private final Stack<Integer> marks;
29 26
 	private final TT eof;
27
+	private final TT invalid;
30 28
 	private final int tabSize = 4;
29
+	private final TokenFactory<T, TT> factory;
31 30
 	
32
-    private PositionedToken next;
31
+    private PositionedToken<T> next;
33 32
 	
34 33
     private int nextChar;
35 34
     private int line;
36 35
     private int lineOffset;
37 36
 	
38
-    private int tokenMemoryOffset;
39
-    private int tokenMemoryCurrent;
40
-    
41 37
     /**
42 38
      * Creates a token stream using the specified reader and DFA.
43 39
      *
@@ -46,25 +42,28 @@ public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> imp
46 42
      * @param dfa DFA to tokenize the stream
47 43
 	 * @param eof end of file token type
48 44
      */
49
-    public TokenParser(String filename, Reader reader, CompiledDFA<TT> dfa, TT eof)
45
+    public TokenParser(
46
+			String filename,
47
+			Reader reader, 
48
+			CompiledDFA<TT> dfa,
49
+			TT eof,
50
+			TT invalid,
51
+			TokenFactory<T, TT> factory)
50 52
 	{
51 53
 		if (eof.isWhitespace()) // important for the advance() method
52 54
 			throw new IllegalArgumentException("EOF cannot be whitespace");
53 55
 		
54
-        tokenMemoryOffset = 0;
55
-        tokenMemoryCurrent = 0;
56
-        tokenMemory = new LinkedList<>();
57
-        marks = new Stack<>();
58
-        
59 56
         this.reader = new CountingReader(reader);
60 57
         this.dfa = dfa;
61 58
 		this.filename = filename;
62 59
 		this.eof = eof;
60
+		this.invalid = invalid;
61
+		this.factory = factory;
63 62
 		
64 63
 		try {
65 64
 	        nextChar = this.reader.read();
66 65
 		} catch (IOException ex) {
67
-			ioException(ex);
66
+			throw new CompileException(getPosition(), CompileExceptionCode.INTERNAL_ERROR, ex.getMessage());
68 67
 		}
69 68
 		
70 69
         line = 1;
@@ -80,102 +79,23 @@ public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> imp
80 79
      * @param dfa DFA to tokenize the stream
81 80
 	 * @param eof end of file token type
82 81
      */
83
-    public TokenParser(String filename, String data, CompiledDFA<TT> dfa, TT eof)
82
+    public TokenParser(String filename, String data, CompiledDFA<TT> dfa, TT eof, TT invalid, TokenFactory<T, TT> factory)
84 83
 	{
85
-        this(filename, new StringReader(data), dfa, eof);
84
+        this(filename, new StringReader(data), dfa, eof, invalid, factory);
86 85
     }
87 86
 	
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
-    
87
+	@Override
103 88
     public T peek()
104 89
 	{
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
-        }
90
+        return next.token;
135 91
     }
136 92
 	
93
+	@Override
137 94
 	public CodePosition getPosition()
138 95
 	{
139
-		if (tokenMemoryCurrent < tokenMemoryOffset + tokenMemory.size()) {
140
-            return tokenMemory.get((tokenMemoryCurrent) - tokenMemoryOffset).position;
141
-        } else {
142
-            return next.position;
143
-        }
96
+		return next.position;
144 97
 	}
145 98
 	
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 99
 	/**
180 100
 	 * Replaces the current token with another one. Used to split composite tokens.
181 101
 	 * 
@@ -184,99 +104,24 @@ public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> imp
184 104
 	public void replace(TT other) {
185 105
 		next = new PositionedToken(
186 106
 				next.position,
187
-				createToken(
107
+				factory.create(
108
+						other,
188 109
 						next.token.getWhitespaceBefore(),
189
-						next.token.getContent(),
190
-						other));
110
+						next.token.getContent()));
191 111
 	}
192 112
 
193
-    // ===============================
194
-    // === Iterator implementation ===
195
-    // ===============================
196
-
197
-	@Override
198
-    public boolean hasNext()
199
-	{
200
-        return next.token.getType() != eof;
201
-    }
202
-
203 113
 	@Override
204 114
     public T next()
205 115
 	{
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.");
116
+        T result = next.token;
117
+		advance();
118
+		return result;
227 119
     }
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 120
 	
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);
121
+	@Override
122
+	public TT getEOF() {
123
+		return eof;
124
+	}
280 125
 	
281 126
     // =======================
282 127
     // === Private methods ===
@@ -311,7 +156,7 @@ public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> imp
311 156
 					line,
312 157
 					lineOffset);
313 158
 			
314
-            next = new PositionedToken(position, createToken(whitespace, "", eof));
159
+            next = new PositionedToken(position, factory.create(eof, whitespace, ""));
315 160
             return;
316 161
         }
317 162
 		
@@ -335,27 +180,21 @@ public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> imp
335 180
             if (dfa.finals[state] != null) {
336 181
                 if (state == 0) {
337 182
 					value.append((char) nextChar);
338
-					next = new PositionedToken(position, invalidToken(
339
-							whitespace,
340
-							value.toString()));
183
+					next = new PositionedToken(position, factory.create(invalid, value.toString(), whitespace));
341 184
 					nextChar = reader.read();
342 185
 				}
343 186
 				
344
-				next = new PositionedToken(position, createToken(
345
-						whitespace,
346
-						value.toString(), dfa.finals[state]));
187
+				next = new PositionedToken(position, factory.create(dfa.finals[state], value.toString(), whitespace));
347 188
             } else {
348 189
 				if (nextChar < 0 && value.length() == 0)
349 190
 					return; // happens on comments at the end of files
350 191
 				
351 192
 				value.append((char) nextChar);
352
-				next = new PositionedToken(position, invalidToken(
353
-						whitespace,
354
-						value.toString()));
193
+				next = new PositionedToken(position, factory.create(invalid, value.toString(), whitespace));
355 194
 				nextChar = reader.read();
356 195
             }
357 196
         } catch (IOException ex) {
358
-            ioException(ex);
197
+			throw new CompileException(getPosition(), CompileExceptionCode.INTERNAL_ERROR, ex.getMessage());
359 198
         }
360 199
     }
361 200
 
@@ -399,7 +238,7 @@ public abstract class TokenParser<T extends Token<TT>, TT extends TokenType> imp
399 238
         }
400 239
     }
401 240
 	
402
-	private class PositionedToken {
241
+	public static class PositionedToken<T> {
403 242
 		public final CodePosition position;
404 243
 		public final T token;
405 244
 		

+ 27
- 12
Parser/src/main/java/org/openzen/zenscript/lexer/TokenStream.java View File

@@ -6,6 +6,8 @@
6 6
 package org.openzen.zenscript.lexer;
7 7
 
8 8
 import org.openzen.zenscript.shared.CodePosition;
9
+import org.openzen.zenscript.shared.CompileException;
10
+import org.openzen.zenscript.shared.CompileExceptionCode;
9 11
 
10 12
 /**
11 13
  *
@@ -14,23 +16,36 @@ import org.openzen.zenscript.shared.CodePosition;
14 16
 public interface TokenStream<TT extends TokenType, T extends Token<TT>> {
15 17
 	T peek();
16 18
 	
17
-	boolean isNext(TT type);
18
-	
19
-	T optional(TT type);
20
-	
21
-	T required(TT type, String error);
22
-	
23
-	void pushMark();
24
-	
25
-	void popMark();
26
-	
27
-	void reset();
19
+	default boolean isNext(TT type) {
20
+		return peek().getType() == type;
21
+	}
22
+	
23
+	default T optional(TT type) {
24
+		if (peek().getType() == type) {
25
+            return next();
26
+        } else {
27
+            return null;
28
+        }
29
+	}
30
+	
31
+	default T required(TT type, String error) throws CompileException {
32
+		T t = peek();
33
+        if (t.getType() == type) {
34
+            return next();
35
+        } else {
36
+			throw new CompileException(getPosition(), CompileExceptionCode.UNEXPECTED_TOKEN, error);
37
+        }
38
+    }
28 39
 	
29 40
 	void replace(TT other);
30 41
 	
31
-	boolean hasNext();
42
+	default boolean hasNext() {
43
+		return peek().getType() != getEOF();
44
+	}
32 45
 	
33 46
 	T next();
34 47
 	
35 48
 	CodePosition getPosition();
49
+	
50
+	TT getEOF();
36 51
 }

+ 85
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/WhitespaceFilteringParser.java View File

@@ -0,0 +1,85 @@
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 org.openzen.zenscript.shared.CodePosition;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class WhitespaceFilteringParser<TT extends TokenType, T extends Token<TT>> implements TokenStream<TT, T> {
15
+	private final TokenStream<TT, T> stream;
16
+	private T next;
17
+	private CodePosition position;
18
+	private String whitespace;
19
+	
20
+	public WhitespaceFilteringParser(TokenStream<TT, T> stream) {
21
+		this.stream = stream;
22
+		advance();
23
+	}
24
+	
25
+	public String getLastWhitespace() {
26
+		return whitespace;
27
+	}
28
+	
29
+	public void skipWhitespaceNewline() {
30
+		int index = whitespace.indexOf('\n');
31
+		if (index >= 0)
32
+			whitespace = whitespace.substring(index + 1);
33
+	}
34
+	
35
+	public String grabWhitespaceLine() {
36
+		if (whitespace.contains("\n")) {
37
+			int index = whitespace.indexOf('\n');
38
+			String result = whitespace.substring(0, index);
39
+			whitespace = whitespace.substring(index + 1);
40
+			return result;
41
+		} else {
42
+			whitespace = "";
43
+			return whitespace;
44
+		}
45
+	}
46
+
47
+	@Override
48
+	public T peek() {
49
+		return next;
50
+	}
51
+
52
+	@Override
53
+	public void replace(TT other) {
54
+		stream.replace(other);
55
+		next = peek();
56
+	}
57
+
58
+	@Override
59
+	public T next() {
60
+		T result = next;
61
+		advance();
62
+		return result;
63
+	}
64
+
65
+	@Override
66
+	public CodePosition getPosition() {
67
+		return position;
68
+	}
69
+
70
+	@Override
71
+	public TT getEOF() {
72
+		return stream.getEOF();
73
+	}
74
+	
75
+	private void advance() {
76
+		whitespace = "";
77
+		position = stream.getPosition();
78
+		next = stream.next();
79
+		while (next.getType().isWhitespace()) {
80
+			whitespace += next.getContent();
81
+			position = stream.getPosition();
82
+			next = stream.next();
83
+		}
84
+	}
85
+}

+ 105
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenFactory.java View File

@@ -0,0 +1,105 @@
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.util.HashMap;
9
+import java.util.Map;
10
+import static org.openzen.zenscript.lexer.ZSTokenType.*;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class ZSTokenFactory implements TokenFactory<ZSToken, ZSTokenType> {
17
+	public static final ZSTokenFactory INSTANCE = new ZSTokenFactory();
18
+	
19
+	private static final Map<String, ZSTokenType> KEYWORDS = new HashMap<>();
20
+	
21
+	static {
22
+		KEYWORDS.put("import", K_IMPORT);
23
+		KEYWORDS.put("alias", K_ALIAS);
24
+		KEYWORDS.put("class", K_CLASS);
25
+		KEYWORDS.put("interface", K_INTERFACE);
26
+		KEYWORDS.put("enum", K_ENUM);
27
+		KEYWORDS.put("struct", K_STRUCT);
28
+		KEYWORDS.put("expand", K_EXPAND);
29
+		KEYWORDS.put("function", K_FUNCTION);
30
+		KEYWORDS.put("variant", K_VARIANT);
31
+		
32
+		KEYWORDS.put("abstract", K_ABSTRACT);
33
+		KEYWORDS.put("final", K_FINAL);
34
+		KEYWORDS.put("override", K_OVERRIDE);
35
+		KEYWORDS.put("const", K_CONST);
36
+		KEYWORDS.put("private", K_PRIVATE);
37
+		KEYWORDS.put("public", K_PUBLIC);
38
+		KEYWORDS.put("export", K_EXPORT);
39
+		KEYWORDS.put("static", K_STATIC);
40
+		KEYWORDS.put("protected", K_PROTECTED);
41
+		KEYWORDS.put("implicit", K_IMPLICIT);
42
+		KEYWORDS.put("virtual", K_VIRTUAL);
43
+		KEYWORDS.put("extern", K_EXTERN);
44
+		
45
+		KEYWORDS.put("val", K_VAL);
46
+		KEYWORDS.put("var", K_VAR);
47
+		KEYWORDS.put("get", K_GET);
48
+		KEYWORDS.put("implements", K_IMPLEMENTS);
49
+		KEYWORDS.put("set", K_SET);
50
+		
51
+		KEYWORDS.put("void", K_VOID);
52
+		KEYWORDS.put("any", K_ANY);
53
+		KEYWORDS.put("bool", K_BOOL);
54
+		KEYWORDS.put("byte", K_BYTE);
55
+		KEYWORDS.put("sbyte", K_SBYTE);
56
+		KEYWORDS.put("short", K_SHORT);
57
+		KEYWORDS.put("ushort", K_USHORT);
58
+		KEYWORDS.put("int", K_INT);
59
+		KEYWORDS.put("uint", K_UINT);
60
+		KEYWORDS.put("long", K_LONG);
61
+		KEYWORDS.put("ulong", K_ULONG);
62
+		KEYWORDS.put("float", K_FLOAT);
63
+		KEYWORDS.put("double", K_DOUBLE);
64
+		KEYWORDS.put("char", K_CHAR);
65
+		KEYWORDS.put("string", K_STRING);
66
+		
67
+		KEYWORDS.put("if", K_IF);
68
+		KEYWORDS.put("else", K_ELSE);
69
+		KEYWORDS.put("do", K_DO);
70
+		KEYWORDS.put("while", K_WHILE);
71
+		KEYWORDS.put("for", K_FOR);
72
+		KEYWORDS.put("throw", K_THROW);
73
+		KEYWORDS.put("lock", K_LOCK);
74
+		KEYWORDS.put("try", K_TRY);
75
+		KEYWORDS.put("catch", K_CATCH);
76
+		KEYWORDS.put("finally", K_FINALLY);
77
+		KEYWORDS.put("return", K_RETURN);
78
+		KEYWORDS.put("break", K_BREAK);
79
+		KEYWORDS.put("continue", K_CONTINUE);
80
+		KEYWORDS.put("switch", K_SWITCH);
81
+		KEYWORDS.put("case", K_CASE);
82
+		KEYWORDS.put("default", K_DEFAULT);
83
+		
84
+		KEYWORDS.put("in", K_IN);
85
+		KEYWORDS.put("is", K_IS);
86
+		KEYWORDS.put("as", K_AS);
87
+		KEYWORDS.put("match", K_MATCH);
88
+		KEYWORDS.put("throws", K_THROWS);
89
+		
90
+		KEYWORDS.put("this", K_THIS);
91
+		KEYWORDS.put("super", K_SUPER);
92
+		KEYWORDS.put("null", K_NULL);
93
+		KEYWORDS.put("true", K_TRUE);
94
+		KEYWORDS.put("false", K_FALSE);
95
+		KEYWORDS.put("new", K_NEW);
96
+	}
97
+
98
+	@Override
99
+	public ZSToken create(ZSTokenType type, String content, String whitespaceBefore) {
100
+		if (type == T_IDENTIFIER && KEYWORDS.containsKey(content))
101
+			type = KEYWORDS.get(content);
102
+		
103
+		return new ZSToken(type, content, whitespaceBefore);
104
+	}
105
+}

+ 32
- 137
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenParser.java View File

@@ -5,172 +5,67 @@
5 5
  */
6 6
 package org.openzen.zenscript.lexer;
7 7
 
8
-import java.io.IOException;
9 8
 import java.io.Reader;
10
-import java.util.HashMap;
11
-import java.util.Map;
12 9
 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 10
 
18 11
 /**
19 12
  *
20 13
  * @author Hoofdgebruiker
21 14
  */
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);
15
+public class ZSTokenParser extends MemoryTokenStreamImpl<ZSTokenType, ZSToken>
16
+		implements ZSTokenStream {
17
+	public static TokenParser<ZSToken, ZSTokenType> createRaw(String filename, Reader reader) {
18
+		return new TokenParser<>(
19
+				filename,
20
+				reader,
21
+				DFA,
22
+				ZSTokenType.EOF,
23
+				ZSTokenType.INVALID,
24
+				ZSTokenFactory.INSTANCE);
101 25
 	}
102 26
 	
103
-	private String whitespaceBuffer = null;
27
+	public static ZSTokenParser create(String filename, Reader reader) {
28
+		return create(filename, new WhitespaceFilteringParser(createRaw(filename, reader)));
29
+	}
104 30
 	
105
-	public ZSTokenParser(String filename, Reader reader) {
106
-		super(filename, reader, DFA, ZSTokenType.EOF);
31
+	public static ZSTokenParser create(String filename, WhitespaceFilteringParser<ZSTokenType, ZSToken> parser) {
32
+		return new ZSTokenParser(filename, parser);
107 33
 	}
108 34
 	
109
-	@Override
110
-	public String loadWhitespace() {
111
-		if (whitespaceBuffer == null)
112
-			whitespaceBuffer = peek().whitespaceBefore;
35
+	private static final CompiledDFA DFA = CompiledDFA.createLexerDFA(ZSTokenType.values(), ZSTokenType.class);
36
+	
37
+	private final String filename;
38
+	private final WhitespaceFilteringParser whitespaceFilteringParser;
39
+	
40
+	private ZSTokenParser(String filename, WhitespaceFilteringParser<ZSTokenType, ZSToken> parser) {
41
+		super(parser);
113 42
 		
114
-		return whitespaceBuffer;
43
+		this.whitespaceFilteringParser = parser;
44
+		this.filename = filename;
115 45
 	}
116 46
 	
117 47
 	@Override
118
-	public void reloadWhitespace() {
119
-		whitespaceBuffer = peek().whitespaceBefore;
48
+	public String getFilename() {
49
+		return filename;
120 50
 	}
121 51
 	
122 52
 	@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
-		}
53
+	public String getLastWhitespace() {
54
+		return whitespaceFilteringParser.getLastWhitespace();
139 55
 	}
140 56
 	
141 57
 	@Override
142 58
 	public void skipWhitespaceNewline() {
143
-		loadWhitespace();
144
-		int index = whitespaceBuffer.indexOf('\n');
145
-		if (index >= 0)
146
-			whitespaceBuffer = whitespaceBuffer.substring(index + 1);
59
+		whitespaceFilteringParser.skipWhitespaceNewline();
147 60
 	}
148 61
 	
149 62
 	@Override
150 63
 	public WhitespaceInfo collectWhitespaceInfo(String whitespace, boolean skipLineBefore) {
151
-		return WhitespaceInfo.from(whitespace, grabWhitespaceLine(), skipLineBefore);
64
+		return WhitespaceInfo.from(whitespace, whitespaceFilteringParser.grabWhitespaceLine(), skipLineBefore);
152 65
 	}
153 66
 	
154 67
 	@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.
68
+	public ZSTokenType getEOF() {
69
+		return ZSTokenType.EOF;
175 70
 	}
176 71
 }

+ 2
- 6
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenStream.java View File

@@ -11,14 +11,10 @@ import org.openzen.zenscript.codemodel.WhitespaceInfo;
11 11
  *
12 12
  * @author Hoofdgebruiker
13 13
  */
14
-public interface ZSTokenStream extends TokenStream<ZSTokenType, ZSToken> {
14
+public interface ZSTokenStream extends MemoryTokenStream<ZSTokenType, ZSToken> {
15 15
 	String getFilename();
16 16
 	
17
-	String loadWhitespace();
18
-	
19
-	void reloadWhitespace();
20
-	
21
-	String grabWhitespace();
17
+	String getLastWhitespace();
22 18
 	
23 19
 	void skipWhitespaceNewline();
24 20
 	

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

@@ -58,7 +58,7 @@ public class ParsedFile {
58 58
 	}
59 59
 	
60 60
 	public static ParsedFile parse(ZSPackage pkg, String filename, Reader reader) throws IOException {
61
-		ZSTokenParser tokens = new ZSTokenParser(filename, reader);
61
+		ZSTokenParser tokens = ZSTokenParser.create(filename, reader);
62 62
 		return parse(pkg, tokens);
63 63
 	}
64 64
 	

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

@@ -45,11 +45,9 @@ public abstract class ParsedStatement {
45 45
 	}
46 46
 	
47 47
 	public static ParsedStatementBlock parseBlock(ZSTokenStream parser, boolean isFirst) {
48
-		String ws = parser.grabWhitespace();
48
+		String ws = parser.getLastWhitespace();
49 49
 		CodePosition position = parser.getPosition();
50 50
 		parser.required(T_AOPEN, "{ expected");
51
-
52
-		parser.reloadWhitespace();
53 51
 		parser.skipWhitespaceNewline();
54 52
 
55 53
 		ArrayList<ParsedStatement> statements = new ArrayList<>();
@@ -70,7 +68,7 @@ public abstract class ParsedStatement {
70 68
 	}
71 69
 	
72 70
 	public static ParsedStatement parse(ZSTokenStream parser, boolean isFirst) {
73
-		String ws = parser.grabWhitespace();
71
+		String ws = parser.getLastWhitespace();
74 72
 		CodePosition position = parser.getPosition();
75 73
 		ZSToken next = parser.peek();
76 74
 		switch (next.getType()) {
@@ -113,7 +111,6 @@ public abstract class ParsedStatement {
113 111
 				ParsedStatement onIf = parse(parser);
114 112
 				ParsedStatement onElse = null;
115 113
 				if (parser.optional(K_ELSE) != null) {
116
-					parser.reloadWhitespace();
117 114
 					parser.skipWhitespaceNewline();
118 115
 					onElse = parse(parser);
119 116
 				}

Loading…
Cancel
Save