Mercurial > projects > dang
annotate parser/Parser.d @ 48:b6c1dc30ca4b new_gen
Only tests that dont pass now are structs and switches
As far as the parser is concerned assignments are binary expressions
Fixed a bug in codegen of if's - it is important to remember that the
builder might be positioned at a new block after generating sub-statements
author | Anders Halager <halager@gmail.com> |
---|---|
date | Thu, 24 Apr 2008 19:42:53 +0200 |
parents | b0a691727a0c |
children | c96cdcbdb9d6 |
rev | line source |
---|---|
1 | 1 module parser.Parser; |
2 | |
3 import lexer.Lexer, | |
4 lexer.Token; | |
5 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
6 import parser.Action; |
1 | 7 |
21
0fb2d13dce37
Now working with gdc also (gdc use reverse paremeter validating on function calls)
johnsen@johnsen-laptop
parents:
12
diff
changeset
|
8 import misc.Error; |
0fb2d13dce37
Now working with gdc also (gdc use reverse paremeter validating on function calls)
johnsen@johnsen-laptop
parents:
12
diff
changeset
|
9 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
10 import basic.SmallArray; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
11 |
1 | 12 import tango.io.Stdout, |
13 Integer = tango.text.convert.Integer; | |
14 | |
15 class Parser | |
16 { | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
17 Action action; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
18 alias Object Exp; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
19 alias Object Stmt; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
20 alias Object Decl; |
1 | 21 |
22 public: | |
23 Decl[] parse(Lexer lexer) | |
24 { | |
25 this.lexer = lexer; | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
26 action = new AstAction; |
1 | 27 |
28 | |
29 Decl[] declarations; | |
30 | |
31 while(lexer.peek.type != Tok.EOF) | |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
32 declarations ~= parseDecl(); |
1 | 33 |
34 return declarations; | |
35 } | |
36 | |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
37 Decl parseDecl() |
1 | 38 { |
28
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
39 Token t = lexer.peek; |
1 | 40 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
41 if (t.isBasicType || t.isIdentifier) |
1 | 42 { |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
43 Id type = Id(lexer.next); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
44 Id iden = Id(require(Tok.Identifier)); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
45 Token next = lexer.peek(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
46 if (next.type == Tok.Seperator) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
47 { |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
48 Token sep = lexer.next(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
49 return action.actOnDeclarator(type, iden, null); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
50 } |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
51 else if (next.type == Tok.Assign) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
52 { |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
53 Token assign = lexer.next(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
54 Exp exp = parseExpression(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
55 require(Tok.Seperator); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
56 return action.actOnDeclarator(type, iden, exp); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
57 } |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
58 else if (next.type == Tok.OpenParentheses) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
59 return parseFunc(type, iden); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
60 else |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
61 throw error(__LINE__, PE.UnexpectedTok) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
62 .tok(next) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
63 .arg(next.getType); |
1 | 64 } |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
65 else if (t.type == Tok.Struct) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
66 { |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
67 } |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
68 char[] c = t.getType; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
69 throw error(__LINE__, PE.UnexpectedTok).tok(t).arg(c); |
1 | 70 } |
71 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
72 /** |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
73 Parse statements. |
28
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
74 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
75 This is the place to attack! |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
76 */ |
1 | 77 Stmt parseStatement() |
78 { | |
79 Token t = lexer.peek; | |
80 | |
81 switch(t.type) | |
82 { | |
83 case Tok.Return: | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
84 Token ret = lexer.next; |
46 | 85 Exp exp; |
86 if (lexer.peek.type != Tok.Seperator) | |
87 exp = parseExpression(); | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
88 require(Tok.Seperator); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
89 return action.actOnReturnStmt(ret, exp); |
5
2c5a8f4c254a
Added very simple if support.
Anders Halager <halager@gmail.com>
parents:
1
diff
changeset
|
90 |
45 | 91 /* |
92 if (cond) | |
93 single statement | compound statement | |
94 [else | |
95 single statement | compound statement] | |
96 */ | |
5
2c5a8f4c254a
Added very simple if support.
Anders Halager <halager@gmail.com>
parents:
1
diff
changeset
|
97 case Tok.If: |
45 | 98 Token _if = lexer.next(); |
99 | |
100 require(Tok.OpenParentheses); | |
101 Exp cond = parseExpression(); | |
102 require(Tok.CloseParentheses); | |
103 | |
104 Stmt thenB = parseSingleOrCompoundStatement(); | |
105 | |
106 // if there is no else part we use the if as token, to have | |
107 // something than can be passed along | |
108 Token _else = _if; | |
109 Stmt elseB; | |
110 if (lexer.peek.type == Tok.Else) | |
111 { | |
112 _else = lexer.next; | |
113 elseB = parseSingleOrCompoundStatement(); | |
114 } | |
115 | |
116 return action.actOnIfStmt(_if, cond, thenB, _else, elseB); | |
5
2c5a8f4c254a
Added very simple if support.
Anders Halager <halager@gmail.com>
parents:
1
diff
changeset
|
117 |
47
b0a691727a0c
Stricter while - the () was optional before
Anders Halager <halager@gmail.com>
parents:
46
diff
changeset
|
118 /* |
b0a691727a0c
Stricter while - the () was optional before
Anders Halager <halager@gmail.com>
parents:
46
diff
changeset
|
119 while (cond) |
b0a691727a0c
Stricter while - the () was optional before
Anders Halager <halager@gmail.com>
parents:
46
diff
changeset
|
120 single statement | compound statement |
b0a691727a0c
Stricter while - the () was optional before
Anders Halager <halager@gmail.com>
parents:
46
diff
changeset
|
121 */ |
11
642c6a998fd9
Support for while statements and fixed scope for if
Anders Halager <halager@gmail.com>
parents:
10
diff
changeset
|
122 case Tok.While: |
46 | 123 Token _while = lexer.next; |
47
b0a691727a0c
Stricter while - the () was optional before
Anders Halager <halager@gmail.com>
parents:
46
diff
changeset
|
124 require(Tok.OpenParentheses); |
46 | 125 Exp cond = parseExpression(); |
47
b0a691727a0c
Stricter while - the () was optional before
Anders Halager <halager@gmail.com>
parents:
46
diff
changeset
|
126 require(Tok.CloseParentheses); |
46 | 127 Stmt bodyStmt = parseSingleOrCompoundStatement(); |
128 return action.actOnWhileStmt(_while, cond, bodyStmt); | |
5
2c5a8f4c254a
Added very simple if support.
Anders Halager <halager@gmail.com>
parents:
1
diff
changeset
|
129 |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
130 /* |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
131 One of four things: |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
132 A declaration of a function/variable `type id ...` |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
133 A direct assignment `id = exp;` |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
134 An indirect assignment `id.id = exp` |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
135 Some sort of free standing expression |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
136 |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
137 The assignments should be handled as binary expressions? |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
138 */ |
1 | 139 case Tok.Identifier: |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
140 Token iden = lexer.peek; |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
141 Token n = lexer.peek(1); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
142 // Must be an decl, if we start with a basic type, or two |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
143 // identifiers in a row |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
144 if (iden.isBasicType() || n.isIdentifier()) |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
145 { |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
146 // manually hardcoded to only support "type id [= exp];" |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
147 // as that is the only thing the codegen understands |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
148 Id type = Id(lexer.next); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
149 Id id = Id(lexer.next); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
150 Exp init; |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
151 if (skip(Tok.Assign)) |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
152 init = parseExpression(); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
153 require(Tok.Seperator); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
154 Decl d = action.actOnDeclarator(type, id, init); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
155 return action.actOnDeclStmt(d); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
156 } |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
157 // Expression: a.b, a = b, a(b) etc. |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
158 else |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
159 { |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
160 Exp exp = parseExpression(); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
161 require(Tok.Seperator); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
162 return action.actOnExprStmt(exp); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
163 } |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
164 break; |
1 | 165 |
36
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
166 case Tok.Switch: |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
167 throw error(__LINE__, ":(").tok(lexer.peek); |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
168 return null; |
36
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
169 |
1 | 170 default: |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
171 if (t.isBasicType()) |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
172 goto case Tok.Identifier; |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
173 throw error(__LINE__, ":(").tok(lexer.peek); |
1 | 174 } |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
175 throw error(__LINE__, "").tok(t); |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
176 return null; |
1 | 177 } |
178 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
179 /** |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
180 Parses a function/method given the already parsed return type and name |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
181 */ |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
182 Decl parseFunc(ref Id type, ref Id name) |
1 | 183 { |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
184 Decl func = action.actOnStartOfFunctionDef(type, name); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
185 parseFuncArgs(func); |
1 | 186 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
187 Stmt stmt = parseCompoundStatement(); |
1 | 188 |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
189 return action.actOnEndOfFunction(func, stmt); |
1 | 190 } |
191 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
192 /** |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
193 Parse the function arguments, assumes current token is (. |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
194 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
195 Both the intitial paren and the ending paren is consumed. |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
196 */ |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
197 void parseFuncArgs(Decl func) |
1 | 198 { |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
199 require(Tok.OpenParentheses); // Remove the "(" token. |
1 | 200 |
201 while(lexer.peek.type != Tok.CloseParentheses) | |
202 { | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
203 auto t = parseType(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
204 auto i = parseIdentifier(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
205 action.addFuncArg(func, t, i); |
1 | 206 |
207 if(lexer.peek.type == Tok.Comma) | |
208 lexer.next; | |
209 } | |
210 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
211 require(Tok.CloseParentheses); // Remove the ")" |
1 | 212 } |
213 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
214 /** |
45 | 215 Parse either a block, or a single statement as allowed after if, while |
216 and for. | |
217 */ | |
218 Stmt parseSingleOrCompoundStatement() | |
219 { | |
220 if (lexer.peek.type == Tok.OpenBrace) | |
221 return parseCompoundStatement(); | |
222 return parseStatement(); | |
223 } | |
224 /** | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
225 Parses a function-body or similar, expects { to be current token. |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
226 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
227 Will consume both the starting { and ending } |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
228 */ |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
229 Stmt parseCompoundStatement() |
1 | 230 { |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
231 Token lbrace = require(Tok.OpenBrace); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
232 SmallArray!(Stmt, 32) stmts; // Try to use the stack only |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
233 while (lexer.peek.type != Tok.CloseBrace) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
234 stmts ~= parseStatement(); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
235 Token rbrace = require(Tok.CloseBrace); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
236 return action.actOnCompoundStmt(lbrace, rbrace, stmts.unsafe()); |
1 | 237 } |
238 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
239 Id parseIdentifier() |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
240 { |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
241 Token tok = lexer.next; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
242 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
243 if (tok.type is Tok.Identifier) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
244 return Id(tok); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
245 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
246 throw error(__LINE__, PE.UnexpectedTokSingle) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
247 .arg(tok.getType) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
248 .arg(Tok.Identifier) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
249 .tok(tok); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
250 } |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
251 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
252 Id parseType() |
1 | 253 { |
254 Token type = lexer.next; | |
255 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
256 if (type.isBasicType || type.type == Tok.Identifier) |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
257 return Id(type); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
258 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
259 char[] c = type.getType; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
260 error(__LINE__, "Unexpected token in Type parsing. Got %0").arg(c); |
1 | 261 } |
262 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
263 private: |
1 | 264 // -- Expression parsing -- // |
28
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
265 Exp parseExpIdentifier(Exp target) |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
266 { |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
267 switch(lexer.peek.type) |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
268 { |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
269 case Tok.Dot: |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
270 switch(lexer.peek(1).type) |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
271 { |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
272 case Tok.Identifier: |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
273 Token op = lexer.next; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
274 Id member = Id(lexer.next); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
275 Exp exp = action.actOnMemberReference(target, op.location, member); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
276 return parseExpIdentifier(exp); |
28
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
277 default: |
30
3147a52d1247
Ooops.. should have compiled before commit.. now works again
Anders Halager <halager@gmail.com>
parents:
29
diff
changeset
|
278 Token t = lexer.peek(1); |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
279 throw error(__LINE__, "Expected identifier after '.'").tok(t); |
28
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
280 } |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
281 default: |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
282 return target; |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
283 } |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
284 } |
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
285 |
1 | 286 Exp parseExpression(int p = 0) |
287 { | |
288 auto exp = P(); | |
289 Token next = lexer.peek(); | |
290 BinOp* op = null; | |
291 while ((op = binary(next.type)) != null && op.prec >= p) | |
292 { | |
293 lexer.next(); | |
294 int q = op.leftAssoc? 1 + op.prec : op.prec; | |
295 auto exp2 = parseExpression(q); | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
296 exp = action.actOnBinaryOp(op.operator, exp, exp2); |
1 | 297 next = lexer.peek(); |
298 } | |
299 | |
300 return exp; | |
301 } | |
302 | |
303 Exp P() | |
304 { | |
305 Token next = lexer.next(); | |
306 if (auto op = unary(next.type)) | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
307 return action.actOnUnaryOp(next, parseExpression(op.prec)); |
1 | 308 else if (next.type == Tok.OpenParentheses) |
309 { | |
310 auto e = parseExpression(0); | |
311 require(Tok.CloseParentheses); | |
312 return e; | |
313 } | |
314 else if (next.type == Tok.Identifier) | |
315 { | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
316 Exp value = action.actOnIdentifierExp(Id(next)); |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
317 Exp iden = parseExpIdentifier(value); |
1 | 318 switch(lexer.peek.type) |
319 { | |
320 case Tok.OpenParentheses: | |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
321 Token lp = lexer.next; |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
322 SmallArray!(Exp, 8) args; |
1 | 323 while(lexer.peek.type != Tok.CloseParentheses) |
324 { | |
325 if(lexer.peek.type == Tok.Comma) | |
326 lexer.next; | |
327 args ~= parseExpression(); | |
328 } | |
329 | |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
330 Token rp = lexer.next(); |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
331 return action.actOnCallExpr(iden, lp, args.unsafe(), rp); |
1 | 332 |
333 default: | |
28
69464d465284
Now supporting structs - both read and write. Still a few errors though, so watch out.
Anders Johnsen <skabet@gmail.com>
parents:
22
diff
changeset
|
334 return iden; |
1 | 335 } |
336 } | |
337 else if (next.type == Tok.Integer) | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
338 return action.actOnNumericConstant(next); |
1 | 339 |
340 Stdout.formatln("{}", next.getType); | |
341 assert(0, "Should not happen"); | |
342 } | |
343 | |
344 struct UnOp | |
345 { | |
346 Tok tokenType; | |
347 int prec; | |
348 } | |
349 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
350 static const UnOp[] _unary = [{Tok.Sub, 4}]; |
1 | 351 UnOp* unary(Tok t) |
352 { | |
353 foreach (ref op; _unary) | |
354 if (op.tokenType == t) | |
355 return &op; | |
356 return null; | |
357 } | |
358 | |
359 struct BinOp | |
360 { | |
361 Tok tokenType; | |
362 int prec; | |
363 bool leftAssoc; | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
364 Operator operator; |
1 | 365 } |
366 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
367 static const BinOp[] _binary = |
1 | 368 [ |
48
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
369 {Tok.Assign, 1, false, Operator.Assign}, |
b6c1dc30ca4b
Only tests that dont pass now are structs and switches
Anders Halager <halager@gmail.com>
parents:
47
diff
changeset
|
370 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
371 {Tok.Eq, 2, true, Operator.Eq}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
372 {Tok.Ne, 2, true, Operator.Ne}, |
10
2f493057cf17
Some support for the rest of the boolean operators
Anders Halager <halager@gmail.com>
parents:
7
diff
changeset
|
373 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
374 {Tok.Lt, 2, true, Operator.Lt}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
375 {Tok.Le, 2, true, Operator.Le}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
376 {Tok.Gt, 2, true, Operator.Gt}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
377 {Tok.Ge, 2, true, Operator.Ge}, |
10
2f493057cf17
Some support for the rest of the boolean operators
Anders Halager <halager@gmail.com>
parents:
7
diff
changeset
|
378 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
379 {Tok.Add, 3, true, Operator.Add}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
380 {Tok.Sub, 3, true, Operator.Sub}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
381 |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
382 {Tok.Mul, 5, true, Operator.Mul}, |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
383 {Tok.Div, 5, true, Operator.Div} |
1 | 384 ]; |
385 BinOp* binary(Tok t) | |
386 { | |
387 foreach (ref op; _binary) | |
388 if (op.tokenType == t) | |
389 return &op; | |
390 return null; | |
391 } | |
392 | |
393 private: | |
394 | |
36
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
395 Token require(Tok t) |
1 | 396 { |
397 if (lexer.peek().type != t) | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
398 throw error(__LINE__, PE.UnexpectedTokSingle) |
29
41d23f2762c3
Merge, and updated Error class
Anders Halager <halager@gmail.com>
parents:
28
diff
changeset
|
399 .arg(lexer.peek.getType) |
33
084c2c147c4f
Improvements to the Error class.
Anders Halager <halager@gmail.com>
parents:
30
diff
changeset
|
400 .arg(t); |
36
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
401 return lexer.next(); |
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
402 } |
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
403 |
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
404 bool skip(Tok t) |
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
405 { |
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
406 if (lexer.peek().type != t) |
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
407 return false; |
1 | 408 lexer.next(); |
36
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
409 return true; |
1 | 410 } |
411 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
412 Error error(uint line, char[] errMsg) |
1 | 413 { |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
414 Location loc = lexer.peek.location; |
33
084c2c147c4f
Improvements to the Error class.
Anders Halager <halager@gmail.com>
parents:
30
diff
changeset
|
415 auto e = |
084c2c147c4f
Improvements to the Error class.
Anders Halager <halager@gmail.com>
parents:
30
diff
changeset
|
416 new Error("Parser.d(" ~ Integer.toString(line) ~ "): " ~errMsg); |
084c2c147c4f
Improvements to the Error class.
Anders Halager <halager@gmail.com>
parents:
30
diff
changeset
|
417 e.loc(loc); |
084c2c147c4f
Improvements to the Error class.
Anders Halager <halager@gmail.com>
parents:
30
diff
changeset
|
418 return e; |
1 | 419 } |
420 | |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
421 struct PE |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
422 { |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
423 static char[] |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
424 UnexpectedTokMulti = "Unexpected token, got %0 expected one of %1", |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
425 UnexpectedTokSingle = "Unexpected token, got %0 expected %1", |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
426 UnexpectedTok = "Unexpected token %0"; |
36
ce17bea8e9bd
Switch statements support
Anders Halager <halager@gmail.com>
parents:
33
diff
changeset
|
427 |
44
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
428 static char[] |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
429 CaseValueMustBeInt = "Cases can only be integer literals"; |
495188f9078e
Big update - Moving towards a better, more seperated parser
Anders Halager <halager@gmail.com>
parents:
37
diff
changeset
|
430 } |
33
084c2c147c4f
Improvements to the Error class.
Anders Halager <halager@gmail.com>
parents:
30
diff
changeset
|
431 |
1 | 432 Lexer lexer; |
433 } |