Mercurial > lcfOS
annotate python/ppci/c3/parser.py @ 395:3b0c495e3008
Speed improvements
author | Windel Bouwman |
---|---|
date | Fri, 23 May 2014 14:28:03 +0200 |
parents | 988f3fb861e4 |
children | fb3c1f029b30 |
rev | line source |
---|---|
254 | 1 import logging |
354 | 2 from .. import CompilerError |
306 | 3 from .astnodes import Member, Literal, TypeCast, Unop, Binop |
307 | 4 from .astnodes import Assignment, ExpressionStatement, Compound |
315 | 5 from .astnodes import Return, While, If, Empty, For |
296 | 6 from .astnodes import FunctionType, Function, FormalParameter |
354 | 7 from .astnodes import StructureType, DefinedType, PointerType, ArrayType |
393 | 8 from .astnodes import Constant, Variable, Sizeof |
354 | 9 from .astnodes import StructField, Deref, Index |
306 | 10 from .astnodes import Package |
11 from .astnodes import Identifier | |
12 from .astnodes import FunctionCall | |
148 | 13 |
288 | 14 |
148 | 15 class Parser: |
213 | 16 """ Parses sourcecode into an abstract syntax tree (AST) """ |
17 def __init__(self, diag): | |
254 | 18 self.logger = logging.getLogger('c3') |
213 | 19 self.diag = diag |
20 | |
306 | 21 def parseSource(self, tokens): |
334 | 22 self.logger.debug('Parsing source') |
306 | 23 self.tokens = tokens |
24 self.token = self.tokens.__next__() | |
254 | 25 try: |
394 | 26 self.parse_package() |
306 | 27 self.mod.ok = True # Valid until proven wrong :) |
254 | 28 return self.mod |
29 except CompilerError as e: | |
30 self.diag.addDiag(e) | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
31 |
213 | 32 def Error(self, msg): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
33 raise CompilerError(msg, self.token.loc) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
34 |
213 | 35 # Lexer helpers: |
36 def Consume(self, typ): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
37 if self.Peak == typ: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
38 return self.NextToken() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
39 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
40 self.Error('Excected: "{0}", got "{1}"'.format(typ, self.Peak)) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
41 |
213 | 42 @property |
43 def Peak(self): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
44 return self.token.typ |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
45 |
228 | 46 @property |
47 def CurLoc(self): | |
48 return self.token.loc | |
49 | |
213 | 50 def hasConsumed(self, typ): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
51 if self.Peak == typ: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
52 self.Consume(typ) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
53 return True |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
54 return False |
213 | 55 |
56 def NextToken(self): | |
219 | 57 t = self.token |
58 if t.typ != 'END': | |
59 self.token = self.tokens.__next__() | |
60 return t | |
213 | 61 |
215 | 62 def addDeclaration(self, decl): |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
334
diff
changeset
|
63 self.currentPart.add_declaration(decl) |
288 | 64 |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
65 def parseImport(self): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
66 self.Consume('import') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
67 name = self.Consume('ID').val |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
68 self.mod.imports.append(name) |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
69 self.Consume(';') |
213 | 70 |
394 | 71 def parse_package(self): |
72 """ Parse a package definition """ | |
284 | 73 self.Consume('module') |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
74 name = self.Consume('ID') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
75 self.Consume(';') |
296 | 76 self.mod = Package(name.val, name.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
77 self.currentPart = self.mod |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
78 while self.Peak != 'END': |
394 | 79 self.parse_top_level() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
80 self.Consume('END') |
148 | 81 |
394 | 82 def parse_top_level(self): |
83 """ Parse toplevel declaration """ | |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
84 if self.Peak == 'function': |
362 | 85 self.parse_function_def() |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
86 elif self.Peak == 'var': |
394 | 87 self.parse_variable_def() |
306 | 88 # TODO handle variable initialization |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
89 elif self.Peak == 'const': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
90 self.parseConstDef() |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
91 elif self.Peak == 'type': |
394 | 92 self.parse_type_def() |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
93 elif self.Peak == 'import': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
94 self.parseImport() |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
95 else: |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
96 self.Error('Expected function, var, const or type') |
148 | 97 |
213 | 98 def parseDesignator(self): |
301 | 99 """ A designator designates an object with a name. """ |
225 | 100 name = self.Consume('ID') |
306 | 101 return Identifier(name.val, name.loc) |
102 | |
103 def parseIdSequence(self): | |
104 ids = [self.Consume('ID')] | |
105 while self.hasConsumed(','): | |
106 ids.append(self.Consume('ID')) | |
107 return ids | |
148 | 108 |
213 | 109 # Type system |
354 | 110 def PostFixId(self): |
111 pfe = self.PrimaryExpression_Id() | |
112 while self.Peak in ['.']: | |
113 if self.hasConsumed('.'): | |
114 field = self.Consume('ID') | |
115 pfe = Member(pfe, field.val, field.loc) | |
116 else: | |
117 raise Exception() | |
118 return pfe | |
119 | |
120 def PrimaryExpression_Id(self): | |
121 if self.Peak == 'ID': | |
122 return self.parseDesignator() | |
123 self.Error('Expected ID, got {0}'.format(self.Peak)) | |
124 | |
125 def parse_type_spec(self): | |
126 """ Parse type specification """ | |
213 | 127 if self.Peak == 'struct': |
128 self.Consume('struct') | |
129 self.Consume('{') | |
130 mems = [] | |
131 while self.Peak != '}': | |
354 | 132 mem_t = self.parse_type_spec() |
306 | 133 for i in self.parseIdSequence(): |
134 mems.append(StructField(i.val, mem_t)) | |
213 | 135 self.Consume(';') |
136 self.Consume('}') | |
296 | 137 theT = StructureType(mems) |
306 | 138 elif self.Peak == 'enum': |
139 # TODO) | |
140 raise NotImplementedError() | |
213 | 141 else: |
354 | 142 theT = self.PostFixId() |
143 | |
144 # Check for pointer or array suffix: | |
145 while self.Peak in ['*', '[']: | |
146 if self.hasConsumed('*'): | |
147 theT = PointerType(theT) | |
148 elif self.hasConsumed('['): | |
149 if self.Peak == ']': | |
150 size = 0 | |
151 self.Consume(']') | |
152 else: | |
153 size = self.Expression() | |
154 self.Consume(']') | |
155 theT = ArrayType(theT, size) | |
156 else: | |
157 raise Exception() | |
213 | 158 return theT |
159 | |
394 | 160 def parse_type_def(self): |
213 | 161 self.Consume('type') |
354 | 162 newtype = self.parse_type_spec() |
213 | 163 typename = self.Consume('ID') |
164 self.Consume(';') | |
296 | 165 df = DefinedType(typename.val, newtype, typename.loc) |
225 | 166 self.addDeclaration(df) |
213 | 167 |
168 # Variable declarations: | |
394 | 169 def parse_variable_def(self): |
170 """ Parse variable declaration """ | |
272 | 171 self.Consume('var') |
354 | 172 t = self.parse_type_spec() |
306 | 173 for name in self.parseIdSequence(): |
296 | 174 v = Variable(name.val, t) |
272 | 175 v.loc = name.loc |
176 self.addDeclaration(v) | |
177 self.Consume(';') | |
148 | 178 |
213 | 179 def parseConstDef(self): |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
180 self.Consume('const') |
354 | 181 t = self.parse_type_spec() |
306 | 182 while True: |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
183 name = self.Consume('ID') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
184 self.Consume('=') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
185 val = self.Expression() |
296 | 186 c = Constant(name.val, t, val) |
313 | 187 self.addDeclaration(c) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
188 c.loc = name.loc |
306 | 189 if not self.hasConsumed(','): |
190 break | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
191 self.Consume(';') |
288 | 192 |
362 | 193 def parse_function_def(self): |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
194 loc = self.Consume('function').loc |
354 | 195 returntype = self.parse_type_spec() |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
196 fname = self.Consume('ID').val |
296 | 197 f = Function(fname, loc) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
198 self.addDeclaration(f) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
199 savePart = self.currentPart |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
200 self.currentPart = f |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
201 self.Consume('(') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
202 parameters = [] |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
203 if not self.hasConsumed(')'): |
306 | 204 while True: |
354 | 205 typ = self.parse_type_spec() |
272 | 206 name = self.Consume('ID') |
296 | 207 param = FormalParameter(name.val, typ) |
272 | 208 param.loc = name.loc |
209 self.addDeclaration(param) | |
210 parameters.append(param) | |
306 | 211 if not self.hasConsumed(','): |
212 break | |
272 | 213 self.Consume(')') |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
214 paramtypes = [p.typ for p in parameters] |
296 | 215 f.typ = FunctionType(paramtypes, returntype) |
362 | 216 if self.Peak == ';': |
217 self.Consume(';') | |
218 f.body = None | |
219 else: | |
220 f.body = self.parseCompound() | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
221 self.currentPart = savePart |
148 | 222 |
354 | 223 def parse_if(self): |
272 | 224 loc = self.Consume('if').loc |
225 self.Consume('(') | |
226 condition = self.Expression() | |
227 self.Consume(')') | |
306 | 228 yes = self.Statement() |
307 | 229 no = self.Statement() if self.hasConsumed('else') else Empty() |
230 return If(condition, yes, no, loc) | |
148 | 231 |
393 | 232 def parse_switch(self): |
233 loc = self.Consume('switch').loc | |
234 self.Consume('(') | |
235 condition = self.Expression() | |
236 self.Consume(')') | |
237 return Switch(condition, loc) | |
238 | |
394 | 239 def parse_while(self): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
240 loc = self.Consume('while').loc |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
241 self.Consume('(') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
242 condition = self.Expression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
243 self.Consume(')') |
306 | 244 statements = self.Statement() |
307 | 245 return While(condition, statements, loc) |
149 | 246 |
354 | 247 def parse_for(self): |
315 | 248 loc = self.Consume('for').loc |
249 self.Consume('(') | |
250 init = self.Statement() | |
251 self.Consume(';') | |
252 condition = self.Expression() | |
253 self.Consume(';') | |
254 final = self.Statement() | |
255 self.Consume(')') | |
256 statements = self.Statement() | |
257 return For(init, condition, final, statements, loc) | |
258 | |
307 | 259 def parseReturn(self): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
260 loc = self.Consume('return').loc |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
261 if self.Peak == ';': |
296 | 262 expr = Literal(0, loc) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
263 else: |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
264 expr = self.Expression() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
265 self.Consume(';') |
307 | 266 return Return(expr, loc) |
148 | 267 |
307 | 268 def parseCompound(self): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
269 self.Consume('{') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
270 statements = [] |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
271 while not self.hasConsumed('}'): |
306 | 272 statements.append(self.Statement()) |
307 | 273 return Compound(statements) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
274 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
275 def Statement(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
276 # Determine statement type based on the pending token: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
277 if self.Peak == 'if': |
354 | 278 return self.parse_if() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
279 elif self.Peak == 'while': |
394 | 280 return self.parse_while() |
315 | 281 elif self.Peak == 'for': |
354 | 282 return self.parse_for() |
393 | 283 elif self.Peak == 'switch': |
284 return self.parse_switch() | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
285 elif self.Peak == '{': |
307 | 286 return self.parseCompound() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
287 elif self.hasConsumed(';'): |
307 | 288 return Empty() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
289 elif self.Peak == 'var': |
394 | 290 self.parse_variable_def() |
291 return Empty() | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
292 elif self.Peak == 'return': |
307 | 293 return self.parseReturn() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
294 else: |
306 | 295 x = self.UnaryExpression() |
296 if self.Peak == '=': | |
297 # We enter assignment mode here. | |
298 loc = self.Consume('=').loc | |
299 rhs = self.Expression() | |
300 return Assignment(x, rhs, loc) | |
301 else: | |
302 return ExpressionStatement(x, x.loc) | |
148 | 303 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
304 # Expression section: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
305 # We not implement these C constructs: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
306 # a(2), f = 2 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
307 # and this: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
308 # a = 2 < x : 4 ? 1; |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
309 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
310 def Expression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
311 exp = self.LogicalAndExpression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
312 while self.Peak == 'or': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
313 loc = self.Consume('or').loc |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
314 e2 = self.LogicalAndExpression() |
296 | 315 exp = Binop(exp, 'or', e2, loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
316 return exp |
148 | 317 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
318 def LogicalAndExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
319 o = self.EqualityExpression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
320 while self.Peak == 'and': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
321 loc = self.Consume('and').loc |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
322 o2 = self.EqualityExpression() |
296 | 323 o = Binop(o, 'and', o2, loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
324 return o |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
325 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
326 def EqualityExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
327 ee = self.SimpleExpression() |
300 | 328 while self.Peak in ['<', '==', '>', '>=', '<=', '!=']: |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
329 op = self.Consume(self.Peak) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
330 ee2 = self.SimpleExpression() |
296 | 331 ee = Binop(ee, op.typ, ee2, op.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
332 return ee |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
333 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
334 def SimpleExpression(self): |
232 | 335 """ Shift operations before + and - ? """ |
336 e = self.AddExpression() | |
337 while self.Peak in ['>>', '<<']: | |
338 op = self.Consume(self.Peak) | |
339 e2 = self.AddExpression() | |
296 | 340 e = Binop(e, op.typ, e2, op.loc) |
232 | 341 return e |
342 | |
343 def AddExpression(self): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
344 e = self.Term() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
345 while self.Peak in ['+', '-']: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
346 op = self.Consume(self.Peak) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
347 e2 = self.Term() |
296 | 348 e = Binop(e, op.typ, e2, op.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
349 return e |
213 | 350 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
351 def Term(self): |
221 | 352 t = self.BitwiseOr() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
353 while self.Peak in ['*', '/']: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
354 op = self.Consume(self.Peak) |
221 | 355 t2 = self.BitwiseOr() |
296 | 356 t = Binop(t, op.typ, t2, op.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
357 return t |
221 | 358 |
359 def BitwiseOr(self): | |
360 a = self.BitwiseAnd() | |
306 | 361 while self.Peak == '|': |
221 | 362 op = self.Consume(self.Peak) |
363 b = self.BitwiseAnd() | |
296 | 364 a = Binop(a, op.typ, b, op.loc) |
221 | 365 return a |
366 | |
367 def BitwiseAnd(self): | |
368 a = self.CastExpression() | |
306 | 369 while self.Peak == '&': |
221 | 370 op = self.Consume(self.Peak) |
371 b = self.CastExpression() | |
296 | 372 a = Binop(a, op.typ, b, op.loc) |
221 | 373 return a |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
374 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
375 # Domain of unary expressions: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
376 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
377 def CastExpression(self): |
228 | 378 """ |
379 the C-style type cast conflicts with '(' expr ')' | |
380 so introduce extra keyword 'cast' | |
381 """ | |
221 | 382 if self.Peak == 'cast': |
230 | 383 loc = self.Consume('cast').loc |
221 | 384 self.Consume('<') |
354 | 385 t = self.parse_type_spec() |
221 | 386 self.Consume('>') |
387 self.Consume('(') | |
232 | 388 ce = self.Expression() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
389 self.Consume(')') |
296 | 390 return TypeCast(t, ce, loc) |
393 | 391 elif self.Peak == 'sizeof': |
392 return self.sizeof_expression() | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
393 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
394 return self.UnaryExpression() |
230 | 395 |
393 | 396 def sizeof_expression(self): |
394 | 397 """ Compiler internal function to determine size of a type """ |
393 | 398 loc = self.Consume('sizeof').loc |
399 self.Consume('(') | |
400 typ = self.parse_type_spec() | |
401 self.Consume(')') | |
402 return Sizeof(typ, loc) | |
403 | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
404 def UnaryExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
405 if self.Peak in ['&', '*']: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
406 op = self.Consume(self.Peak) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
407 ce = self.CastExpression() |
225 | 408 if op.val == '*': |
296 | 409 return Deref(ce, op.loc) |
225 | 410 else: |
296 | 411 return Unop(op.typ, ce, op.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
412 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
413 return self.PostFixExpression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
414 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
415 def PostFixExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
416 pfe = self.PrimaryExpression() |
315 | 417 while self.Peak in ['[', '.', '->', '(', '++']: |
308 | 418 if self.hasConsumed('['): |
354 | 419 i = self.Expression() |
420 self.Consume(']') | |
421 pfe = Index(pfe, i, i.loc) | |
308 | 422 elif self.hasConsumed('->'): |
423 field = self.Consume('ID') | |
424 pfe = Deref(pfe, pfe.loc) | |
425 pfe = Member(pfe, field.val, field.loc) | |
426 elif self.hasConsumed('.'): | |
427 field = self.Consume('ID') | |
428 pfe = Member(pfe, field.val, field.loc) | |
315 | 429 elif self.Peak == '++': |
430 loc = self.Consume('++').loc | |
431 pfe = Unop('++', pfe, loc) | |
308 | 432 elif self.hasConsumed('('): |
433 # Function call | |
434 args = [] | |
435 if not self.hasConsumed(')'): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
436 args.append(self.Expression()) |
308 | 437 while self.hasConsumed(','): |
438 args.append(self.Expression()) | |
439 self.Consume(')') | |
440 pfe = FunctionCall(pfe, args, pfe.loc) | |
441 else: | |
442 raise Exception() | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
443 return pfe |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
444 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
445 def PrimaryExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
446 if self.hasConsumed('('): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
447 e = self.Expression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
448 self.Consume(')') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
449 return e |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
450 elif self.Peak == 'NUMBER': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
451 val = self.Consume('NUMBER') |
296 | 452 return Literal(val.val, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
453 elif self.Peak == 'REAL': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
454 val = self.Consume('REAL') |
296 | 455 return Literal(val.val, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
456 elif self.Peak == 'true': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
457 val = self.Consume('true') |
296 | 458 return Literal(True, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
459 elif self.Peak == 'false': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
460 val = self.Consume('false') |
296 | 461 return Literal(False, val.loc) |
311 | 462 elif self.Peak == 'STRING': |
463 val = self.Consume('STRING') | |
464 return Literal(val.val, val.loc) | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
465 elif self.Peak == 'ID': |
306 | 466 return self.parseDesignator() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
467 self.Error('Expected NUM, ID or (expr), got {0}'.format(self.Peak)) |
354 | 468 |