Mercurial > lcfOS
annotate python/ppci/c3/parser.py @ 306:b145f8e6050b
Start on c3 rewrite
author | Windel Bouwman |
---|---|
date | Mon, 09 Dec 2013 19:00:21 +0100 |
parents | 6753763d3bec |
children | e609d5296ee9 |
rev | line source |
---|---|
254 | 1 import logging |
301 | 2 from ppci import CompilerError |
306 | 3 from .astnodes import Member, Literal, TypeCast, Unop, Binop |
296 | 4 from .astnodes import Assignment, ExpressionStatement, CompoundStatement |
5 from .astnodes import ReturnStatement, WhileStatement, IfStatement | |
6 from .astnodes import FunctionType, Function, FormalParameter | |
7 from .astnodes import StructureType, DefinedType, PointerType | |
8 from .astnodes import Constant, Variable | |
9 from .astnodes import StructField, Deref | |
306 | 10 from .astnodes import Package |
11 from .astnodes import Identifier | |
12 from .astnodes import FunctionCall | |
13 from .astnodes import EmptyStatement | |
148 | 14 |
288 | 15 |
148 | 16 class Parser: |
213 | 17 """ Parses sourcecode into an abstract syntax tree (AST) """ |
18 def __init__(self, diag): | |
254 | 19 self.logger = logging.getLogger('c3') |
213 | 20 self.diag = diag |
21 | |
306 | 22 def parseSource(self, tokens): |
254 | 23 self.logger.info('Parsing source') |
306 | 24 self.tokens = tokens |
25 self.token = self.tokens.__next__() | |
254 | 26 try: |
27 self.parsePackage() | |
306 | 28 self.mod.ok = True # Valid until proven wrong :) |
254 | 29 return self.mod |
30 except CompilerError as e: | |
31 self.diag.addDiag(e) | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
32 |
213 | 33 def Error(self, msg): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
34 raise CompilerError(msg, self.token.loc) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
35 |
213 | 36 # Lexer helpers: |
37 def Consume(self, typ): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
38 if self.Peak == typ: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
39 return self.NextToken() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
40 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
41 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
|
42 |
213 | 43 @property |
44 def Peak(self): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
45 return self.token.typ |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
46 |
228 | 47 @property |
48 def CurLoc(self): | |
49 return self.token.loc | |
50 | |
213 | 51 def hasConsumed(self, typ): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
52 if self.Peak == typ: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
53 self.Consume(typ) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
54 return True |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
55 return False |
213 | 56 |
57 def NextToken(self): | |
219 | 58 t = self.token |
59 if t.typ != 'END': | |
60 self.token = self.tokens.__next__() | |
61 return t | |
213 | 62 |
215 | 63 def addDeclaration(self, decl): |
64 self.currentPart.declarations.append(decl) | |
288 | 65 |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
66 def parseImport(self): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
67 self.Consume('import') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
68 name = self.Consume('ID').val |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
69 self.mod.imports.append(name) |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
70 self.Consume(';') |
213 | 71 |
72 def parsePackage(self): | |
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': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
79 self.parseTopLevel() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
80 self.Consume('END') |
148 | 81 |
213 | 82 def parseTopLevel(self): |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
83 if self.Peak == 'function': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
84 self.parseFunctionDef() |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
85 elif self.Peak == 'var': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
86 self.parseVarDef() |
306 | 87 # TODO handle variable initialization |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
88 elif self.Peak == 'const': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
89 self.parseConstDef() |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
90 elif self.Peak == 'type': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
91 self.parseTypeDef() |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
92 elif self.Peak == 'import': |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
93 self.parseImport() |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
94 else: |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
232
diff
changeset
|
95 self.Error('Expected function, var, const or type') |
148 | 96 |
213 | 97 def parseDesignator(self): |
301 | 98 """ A designator designates an object with a name. """ |
225 | 99 name = self.Consume('ID') |
306 | 100 return Identifier(name.val, name.loc) |
101 | |
102 def parseIdSequence(self): | |
103 ids = [self.Consume('ID')] | |
104 while self.hasConsumed(','): | |
105 ids.append(self.Consume('ID')) | |
106 return ids | |
148 | 107 |
213 | 108 # Type system |
109 def parseTypeSpec(self): | |
110 # For now, do simple type spec, just parse an ID: | |
111 if self.Peak == 'struct': | |
112 self.Consume('struct') | |
113 self.Consume('{') | |
114 mems = [] | |
115 while self.Peak != '}': | |
116 mem_t = self.parseTypeSpec() | |
306 | 117 for i in self.parseIdSequence(): |
118 mems.append(StructField(i.val, mem_t)) | |
213 | 119 self.Consume(';') |
120 self.Consume('}') | |
296 | 121 theT = StructureType(mems) |
306 | 122 elif self.Peak == 'enum': |
123 # TODO) | |
124 raise NotImplementedError() | |
213 | 125 else: |
306 | 126 theT = self.PostFixExpression() |
213 | 127 # Check for pointer suffix: |
128 while self.hasConsumed('*'): | |
296 | 129 theT = PointerType(theT) |
213 | 130 return theT |
131 | |
132 def parseTypeDef(self): | |
133 self.Consume('type') | |
134 newtype = self.parseTypeSpec() | |
135 typename = self.Consume('ID') | |
136 self.Consume(';') | |
296 | 137 df = DefinedType(typename.val, newtype, typename.loc) |
225 | 138 self.addDeclaration(df) |
213 | 139 |
140 # Variable declarations: | |
141 def parseVarDef(self): | |
272 | 142 self.Consume('var') |
143 t = self.parseTypeSpec() | |
306 | 144 for name in self.parseIdSequence(): |
296 | 145 v = Variable(name.val, t) |
272 | 146 v.loc = name.loc |
147 self.addDeclaration(v) | |
148 self.Consume(';') | |
306 | 149 return EmptyStatement() |
148 | 150 |
213 | 151 def parseConstDef(self): |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
152 self.Consume('const') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
153 t = self.parseTypeSpec() |
306 | 154 while True: |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
155 name = self.Consume('ID') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
156 self.Consume('=') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
157 val = self.Expression() |
296 | 158 c = Constant(name.val, t, val) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
159 c.loc = name.loc |
306 | 160 if not self.hasConsumed(','): |
161 break | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
162 self.Consume(';') |
288 | 163 |
213 | 164 def parseFunctionDef(self): |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
165 loc = self.Consume('function').loc |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
166 returntype = self.parseTypeSpec() |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
167 fname = self.Consume('ID').val |
296 | 168 f = Function(fname, loc) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
169 self.addDeclaration(f) |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
170 savePart = self.currentPart |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
171 self.currentPart = f |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
172 self.Consume('(') |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
173 parameters = [] |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
174 if not self.hasConsumed(')'): |
306 | 175 while True: |
272 | 176 typ = self.parseTypeSpec() |
177 name = self.Consume('ID') | |
296 | 178 param = FormalParameter(name.val, typ) |
272 | 179 param.loc = name.loc |
180 self.addDeclaration(param) | |
181 parameters.append(param) | |
306 | 182 if not self.hasConsumed(','): |
183 break | |
272 | 184 self.Consume(')') |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
185 paramtypes = [p.typ for p in parameters] |
296 | 186 f.typ = FunctionType(paramtypes, returntype) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
187 f.body = self.parseCompoundStatement() |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
188 self.currentPart = savePart |
148 | 189 |
213 | 190 def parseIfStatement(self): |
272 | 191 loc = self.Consume('if').loc |
192 self.Consume('(') | |
193 condition = self.Expression() | |
194 self.Consume(')') | |
306 | 195 yes = self.Statement() |
196 no = self.Statement() if self.hasConsumed('else') else EmptyStatement() | |
296 | 197 return IfStatement(condition, yes, no, loc) |
148 | 198 |
213 | 199 def parseWhileStatement(self): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
200 loc = self.Consume('while').loc |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
201 self.Consume('(') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
202 condition = self.Expression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
203 self.Consume(')') |
306 | 204 statements = self.Statement() |
296 | 205 return WhileStatement(condition, statements, loc) |
149 | 206 |
213 | 207 def parseReturnStatement(self): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
208 loc = self.Consume('return').loc |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
209 if self.Peak == ';': |
296 | 210 expr = Literal(0, loc) |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
211 else: |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
272
diff
changeset
|
212 expr = self.Expression() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
213 self.Consume(';') |
296 | 214 return ReturnStatement(expr, loc) |
148 | 215 |
213 | 216 def parseCompoundStatement(self): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
217 self.Consume('{') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
218 statements = [] |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
219 while not self.hasConsumed('}'): |
306 | 220 statements.append(self.Statement()) |
296 | 221 return CompoundStatement(statements) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
222 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
223 def Statement(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
224 # 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
|
225 if self.Peak == 'if': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
226 return self.parseIfStatement() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
227 elif self.Peak == 'while': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
228 return self.parseWhileStatement() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
229 elif self.Peak == '{': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
230 return self.parseCompoundStatement() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
231 elif self.hasConsumed(';'): |
306 | 232 return EmptyStatement() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
233 elif self.Peak == 'var': |
306 | 234 return self.parseVarDef() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
235 elif self.Peak == 'return': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
236 return self.parseReturnStatement() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
237 else: |
306 | 238 x = self.UnaryExpression() |
239 if self.Peak == '=': | |
240 # We enter assignment mode here. | |
241 loc = self.Consume('=').loc | |
242 rhs = self.Expression() | |
243 return Assignment(x, rhs, loc) | |
244 else: | |
245 return ExpressionStatement(x, x.loc) | |
148 | 246 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
247 # Expression section: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
248 # We not implement these C constructs: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
249 # a(2), f = 2 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
250 # and this: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
251 # a = 2 < x : 4 ? 1; |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
252 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
253 def Expression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
254 exp = self.LogicalAndExpression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
255 while self.Peak == 'or': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
256 loc = self.Consume('or').loc |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
257 e2 = self.LogicalAndExpression() |
296 | 258 exp = Binop(exp, 'or', e2, loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
259 return exp |
148 | 260 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
261 def LogicalAndExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
262 o = self.EqualityExpression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
263 while self.Peak == 'and': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
264 loc = self.Consume('and').loc |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
265 o2 = self.EqualityExpression() |
296 | 266 o = Binop(o, 'and', o2, loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
267 return o |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
268 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
269 def EqualityExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
270 ee = self.SimpleExpression() |
300 | 271 while self.Peak in ['<', '==', '>', '>=', '<=', '!=']: |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
272 op = self.Consume(self.Peak) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
273 ee2 = self.SimpleExpression() |
296 | 274 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
|
275 return ee |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
276 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
277 def SimpleExpression(self): |
232 | 278 """ Shift operations before + and - ? """ |
279 e = self.AddExpression() | |
280 while self.Peak in ['>>', '<<']: | |
281 op = self.Consume(self.Peak) | |
282 e2 = self.AddExpression() | |
296 | 283 e = Binop(e, op.typ, e2, op.loc) |
232 | 284 return e |
285 | |
286 def AddExpression(self): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
287 e = self.Term() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
288 while self.Peak in ['+', '-']: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
289 op = self.Consume(self.Peak) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
290 e2 = self.Term() |
296 | 291 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
|
292 return e |
213 | 293 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
294 def Term(self): |
221 | 295 t = self.BitwiseOr() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
296 while self.Peak in ['*', '/']: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
297 op = self.Consume(self.Peak) |
221 | 298 t2 = self.BitwiseOr() |
296 | 299 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
|
300 return t |
221 | 301 |
302 def BitwiseOr(self): | |
303 a = self.BitwiseAnd() | |
306 | 304 while self.Peak == '|': |
221 | 305 op = self.Consume(self.Peak) |
306 b = self.BitwiseAnd() | |
296 | 307 a = Binop(a, op.typ, b, op.loc) |
221 | 308 return a |
309 | |
310 def BitwiseAnd(self): | |
311 a = self.CastExpression() | |
306 | 312 while self.Peak == '&': |
221 | 313 op = self.Consume(self.Peak) |
314 b = self.CastExpression() | |
296 | 315 a = Binop(a, op.typ, b, op.loc) |
221 | 316 return a |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
317 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
318 # Domain of unary expressions: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
319 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
320 def CastExpression(self): |
228 | 321 """ |
322 the C-style type cast conflicts with '(' expr ')' | |
323 so introduce extra keyword 'cast' | |
324 """ | |
221 | 325 if self.Peak == 'cast': |
230 | 326 loc = self.Consume('cast').loc |
221 | 327 self.Consume('<') |
328 t = self.parseTypeSpec() | |
329 self.Consume('>') | |
330 self.Consume('(') | |
232 | 331 ce = self.Expression() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
332 self.Consume(')') |
296 | 333 return TypeCast(t, ce, loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
334 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
335 return self.UnaryExpression() |
230 | 336 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
337 def UnaryExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
338 if self.Peak in ['&', '*']: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
339 op = self.Consume(self.Peak) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
340 ce = self.CastExpression() |
225 | 341 if op.val == '*': |
296 | 342 return Deref(ce, op.loc) |
225 | 343 else: |
296 | 344 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
|
345 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
346 return self.PostFixExpression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
347 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
348 def PostFixExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
349 pfe = self.PrimaryExpression() |
301 | 350 if self.hasConsumed('('): |
351 # Function call | |
352 args = [] | |
353 if not self.hasConsumed(')'): | |
354 args.append(self.Expression()) | |
355 while self.hasConsumed(','): | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
356 args.append(self.Expression()) |
301 | 357 self.Consume(')') |
358 pfe = FunctionCall(pfe, args, pfe.loc) | |
359 else: | |
360 while self.Peak in ['[', '.', '->']: | |
361 if self.hasConsumed('['): | |
362 raise NotImplementedError('Array not yet implemented') | |
363 elif self.hasConsumed('->'): | |
364 field = self.Consume('ID') | |
365 pfe = Deref(pfe, pfe.loc) | |
306 | 366 pfe = Member(pfe, field.val, field.loc) |
301 | 367 elif self.hasConsumed('.'): |
368 field = self.Consume('ID') | |
306 | 369 pfe = Member(pfe, field.val, field.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
370 return pfe |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
371 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
372 def PrimaryExpression(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
373 if self.hasConsumed('('): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
374 e = self.Expression() |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
375 self.Consume(')') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
376 return e |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
377 elif self.Peak == 'NUMBER': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
378 val = self.Consume('NUMBER') |
296 | 379 return Literal(val.val, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
380 elif self.Peak == 'REAL': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
381 val = self.Consume('REAL') |
296 | 382 return Literal(val.val, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
383 elif self.Peak == 'true': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
384 val = self.Consume('true') |
296 | 385 return Literal(True, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
386 elif self.Peak == 'false': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
387 val = self.Consume('false') |
296 | 388 return Literal(False, val.loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
389 elif self.Peak == 'ID': |
306 | 390 return self.parseDesignator() |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
219
diff
changeset
|
391 self.Error('Expected NUM, ID or (expr), got {0}'.format(self.Peak)) |