1
|
1 module parser.Parser;
|
|
2
|
|
3 import lexer.Lexer,
|
|
4 lexer.Token;
|
|
5
|
|
6 import ast.Exp,
|
|
7 ast.Stmt,
|
|
8 ast.Decl;
|
|
9
|
|
10 import tango.io.Stdout,
|
|
11 Integer = tango.text.convert.Integer;
|
|
12
|
|
13 class Parser
|
|
14 {
|
|
15
|
|
16 public:
|
|
17 Decl[] parse(Lexer lexer)
|
|
18 {
|
|
19 this.lexer = lexer;
|
|
20
|
|
21
|
|
22 Decl[] declarations;
|
|
23
|
|
24 while(lexer.peek.type != Tok.EOF)
|
|
25 {
|
|
26 declarations ~= parseDecl;
|
|
27 }
|
|
28
|
|
29 return declarations;
|
|
30 }
|
|
31
|
|
32 Decl parseDecl()
|
|
33 {
|
|
34 Token t = lexer.next;
|
|
35
|
|
36 switch(t.type)
|
|
37 {
|
|
38 case Tok.Byte, Tok.Ubyte,
|
|
39 Tok.Short, Tok.Ushort,
|
|
40 Tok.Int, Tok.Uint,
|
|
41 Tok.Long, Tok.Ulong,
|
|
42 Tok.Float, Tok.Double,
|
|
43 Tok.Identifier:
|
|
44 Identifier type = new Identifier(t);
|
|
45
|
|
46 Token iden = lexer.next;
|
|
47 switch(iden.type)
|
|
48 {
|
|
49 case Tok.Identifier:
|
|
50 Identifier identifier = new Identifier(iden);
|
|
51 Token p = lexer.peek();
|
|
52 switch(p.type)
|
|
53 {
|
|
54 case Tok.OpenParentheses:
|
|
55 return parseFunc(type, identifier);
|
|
56 case Tok.Seperator:
|
|
57 require(Tok.Seperator);
|
|
58 return new VarDecl(type, identifier, null);
|
|
59 case Tok.Assign:
|
|
60 lexer.next();
|
|
61 auto exp = parseExpression();
|
|
62 require(Tok.Seperator);
|
|
63 return new VarDecl(type, identifier, exp);
|
|
64 default:
|
|
65 char[] c = t.getType;
|
|
66 error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__));
|
|
67 }
|
|
68 break;
|
|
69 default:
|
|
70 char[] c = t.getType;
|
|
71 error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__));
|
|
72 }
|
|
73 break;
|
|
74
|
|
75 case Tok.EOF:
|
|
76 return null;
|
|
77 default:
|
|
78 char[] c = t.getType;
|
|
79 error("Unexpexted token "~c~" at line "~Integer.toString(__LINE__));
|
|
80 }
|
|
81 }
|
|
82
|
|
83 Stmt parseStatement()
|
|
84 {
|
|
85 Token t = lexer.peek;
|
|
86
|
|
87 switch(t.type)
|
|
88 {
|
|
89 case Tok.Return:
|
|
90 lexer.next;
|
|
91 auto ret = new ReturnStmt();
|
|
92 ret.exp = parseExpression();
|
|
93 require(Tok.Seperator);
|
|
94 return ret;
|
|
95 case Tok.Identifier:
|
|
96 Token n = lexer.peek(1);
|
|
97 switch(n.type)
|
|
98 {
|
|
99 case Tok.Assign:
|
|
100 lexer.next;
|
|
101 lexer.next;
|
|
102 auto stmt = new ExpStmt(new AssignExp(new Identifier(t), parseExpression()));
|
|
103 require(Tok.Seperator);
|
|
104 return stmt;
|
|
105 break;
|
|
106
|
|
107 default:
|
|
108 auto e = new ExpStmt(parseExpression());
|
|
109 require(Tok.Seperator);
|
|
110 return e;
|
|
111
|
|
112 }
|
|
113 break;
|
|
114
|
|
115 default:
|
|
116 auto decl = new DeclStmt(parseDecl());
|
|
117 //require(Tok.Seperator);
|
|
118 return decl;
|
|
119 }
|
|
120 return new Stmt();
|
|
121 }
|
|
122
|
|
123 FuncDecl parseFunc(Identifier type, Identifier identifier)
|
|
124 {
|
|
125 VarDecl[] funcArgs = parseFuncArgs();
|
|
126
|
|
127 lexer.next; // Remove the "{"
|
|
128
|
|
129 Stmt[] statements;
|
|
130
|
|
131 while(lexer.peek.type != Tok.CloseBrace)
|
|
132 statements ~= parseStatement();
|
|
133
|
|
134 lexer.next; // Remove "}"
|
|
135
|
|
136 return new FuncDecl(type, identifier, funcArgs, statements);
|
|
137 }
|
|
138
|
|
139 VarDecl[] parseFuncArgs()
|
|
140 {
|
|
141 lexer.next; // Remove the "(" token.
|
|
142
|
|
143 VarDecl[] funcArgs;
|
|
144
|
|
145 while(lexer.peek.type != Tok.CloseParentheses)
|
|
146 {
|
|
147 funcArgs ~= new VarDecl(parseType, parseIdentifier);
|
|
148
|
|
149 if(lexer.peek.type == Tok.Comma)
|
|
150 lexer.next;
|
|
151 }
|
|
152
|
|
153 lexer.next; // Remove the ")"
|
|
154
|
|
155 return funcArgs;
|
|
156 }
|
|
157
|
|
158 Identifier parseIdentifier()
|
|
159 {
|
|
160 Token identifier = lexer.next;
|
|
161
|
|
162 switch(identifier.type)
|
|
163 {
|
|
164 case Tok.Identifier:
|
|
165 return new Identifier(identifier);
|
|
166 break;
|
|
167 default:
|
|
168 error("Unexpexted token in Identifier parsing");
|
|
169 }
|
|
170 }
|
|
171
|
|
172 Identifier parseType()
|
|
173 {
|
|
174 Token type = lexer.next;
|
|
175
|
|
176 switch(type.type)
|
|
177 {
|
|
178 case Tok.Byte, Tok.Ubyte,
|
|
179 Tok.Short, Tok.Ushort,
|
|
180 Tok.Int, Tok.Uint,
|
|
181 Tok.Long, Tok.Ulong,
|
|
182 Tok.Float, Tok.Double,
|
|
183 Tok.Identifier:
|
|
184 return new Identifier(type);
|
|
185 break;
|
|
186 default:
|
|
187 char[] c = type.getType;
|
|
188 error("Unexpexted token in Type parsing. Got "~c);
|
|
189 }
|
|
190 }
|
|
191
|
|
192 // -- Expression parsing -- //
|
|
193 private:
|
|
194 Exp parseExpression(int p = 0)
|
|
195 {
|
|
196 auto exp = P();
|
|
197 Token next = lexer.peek();
|
|
198 BinOp* op = null;
|
|
199 while ((op = binary(next.type)) != null && op.prec >= p)
|
|
200 {
|
|
201 lexer.next();
|
|
202 int q = op.leftAssoc? 1 + op.prec : op.prec;
|
|
203 auto exp2 = parseExpression(q);
|
|
204 exp = new BinaryExp(op.operator, exp, exp2);
|
|
205 next = lexer.peek();
|
|
206 }
|
|
207
|
|
208 return exp;
|
|
209 }
|
|
210
|
|
211 Exp P()
|
|
212 {
|
|
213 Token next = lexer.next();
|
|
214 if (auto op = unary(next.type))
|
|
215 return new NegateExp(parseExpression(op.prec));
|
|
216 else if (next.type == Tok.OpenParentheses)
|
|
217 {
|
|
218 auto e = parseExpression(0);
|
|
219 require(Tok.CloseParentheses);
|
|
220 return e;
|
|
221 }
|
|
222 else if (next.type == Tok.Identifier)
|
|
223 {
|
|
224 switch(lexer.peek.type)
|
|
225 {
|
|
226 case Tok.OpenParentheses:
|
|
227 lexer.next;
|
|
228 Exp[] args;
|
|
229 while(lexer.peek.type != Tok.CloseParentheses)
|
|
230 {
|
|
231 if(lexer.peek.type == Tok.Comma)
|
|
232 {
|
|
233 lexer.next;
|
|
234 }
|
|
235 args ~= parseExpression();
|
|
236 }
|
|
237
|
|
238 lexer.next();
|
|
239 return new CallExp(new Identifier(next), args);
|
|
240
|
|
241 default:
|
|
242 return new Identifier(next);
|
|
243 }
|
|
244 }
|
|
245 else if (next.type == Tok.Integer)
|
|
246 return new IntegerLit(next);
|
|
247
|
|
248 Stdout.formatln("{}", next.getType);
|
|
249 assert(0, "Should not happen");
|
|
250 }
|
|
251
|
|
252 struct UnOp
|
|
253 {
|
|
254 Tok tokenType;
|
|
255 int prec;
|
|
256 }
|
|
257
|
|
258 static UnOp[] _unary = [{Tok.Sub, 4}];
|
|
259 UnOp* unary(Tok t)
|
|
260 {
|
|
261 foreach (ref op; _unary)
|
|
262 if (op.tokenType == t)
|
|
263 return &op;
|
|
264 return null;
|
|
265 }
|
|
266
|
|
267 struct BinOp
|
|
268 {
|
|
269 Tok tokenType;
|
|
270 int prec;
|
|
271 bool leftAssoc;
|
|
272 BinaryExp.Operator operator;
|
|
273 }
|
|
274
|
|
275 static BinOp[] _binary =
|
|
276 [
|
|
277 {Tok.Add, 3, true, BinaryExp.Operator.Add},
|
|
278 {Tok.Sub, 3, true, BinaryExp.Operator.Sub},
|
|
279 {Tok.Mul, 5, true, BinaryExp.Operator.Mul},
|
|
280 {Tok.Div, 5, true, BinaryExp.Operator.Div}
|
|
281 ];
|
|
282 BinOp* binary(Tok t)
|
|
283 {
|
|
284 foreach (ref op; _binary)
|
|
285 if (op.tokenType == t)
|
|
286 return &op;
|
|
287 return null;
|
|
288 }
|
|
289
|
|
290 private:
|
|
291
|
|
292 void require(Tok t)
|
|
293 {
|
|
294 if (lexer.peek().type != t)
|
|
295 error("Unexpexted token: Got '"~lexer.peek.getType~"' Expected '"~typeToString[t]~"'");
|
|
296 lexer.next();
|
|
297 }
|
|
298
|
|
299 void error(char[] errMsg)
|
|
300 {
|
|
301 throw new Exception("Parser error: " ~errMsg);
|
|
302 }
|
|
303
|
|
304 Lexer lexer;
|
|
305 }
|