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