Mercurial > lcfOS
comparison python/c3/parser.py @ 166:da0087b82fbe
Improved type checking
author | Windel Bouwman |
---|---|
date | Fri, 22 Mar 2013 16:15:31 +0100 |
parents | 598d3888a11c |
children | 0b5b2ee6b435 |
comparison
equal
deleted
inserted
replaced
165:598d3888a11c | 166:da0087b82fbe |
---|---|
6 '<': 20, '>': 20, '==': 20, '<=': 20, '>=': 20, '!=': 20, \ | 6 '<': 20, '>': 20, '==': 20, '<=': 20, '>=': 20, '!=': 20, \ |
7 '+': 30, '-': 30, '*': 40, '/': 40 } | 7 '+': 30, '-': 30, '*': 40, '/': 40 } |
8 | 8 |
9 class Parser: | 9 class Parser: |
10 """ Parses sourcecode into an abstract syntax tree (AST) """ | 10 """ Parses sourcecode into an abstract syntax tree (AST) """ |
11 def __init__(self, sema, diag): | 11 def __init__(self, diag): |
12 self.sema = sema | 12 self.sema = semantics.Semantics(diag) |
13 self.diag = diag | 13 self.diag = diag |
14 def parseSource(self, source): | 14 def parseSource(self, source): |
15 self.initLex(source) | 15 self.initLex(source) |
16 try: | 16 try: |
17 self.parsePackage() | 17 self.parsePackage() |
18 except CompilerError as e: | 18 except CompilerError as e: |
19 self.diag.addDiag(e) | 19 self.diag.addDiag(e) |
20 return self.sema.mod | |
20 def Error(self, msg): | 21 def Error(self, msg): |
21 raise CompilerError(msg, self.token.loc) | 22 raise CompilerError(msg, self.token.loc) |
22 # Lexer helpers: | 23 # Lexer helpers: |
23 def Consume(self, typ): | 24 def Consume(self, typ): |
24 if self.Peak == typ: | 25 if self.Peak == typ: |
38 self.Consume(typ) | 39 self.Consume(typ) |
39 return True | 40 return True |
40 return False | 41 return False |
41 def NextToken(self): | 42 def NextToken(self): |
42 t = self.token | 43 t = self.token |
43 if t.typ != 'END': self.token = self.tokens.__next__() | 44 if t.typ != 'END': |
45 self.token = self.tokens.__next__() | |
44 return t | 46 return t |
45 def initLex(self, source): | 47 def initLex(self, source): |
46 self.tokens = lexer.tokenize(source) # Lexical stage | 48 self.tokens = lexer.tokenize(source) # Lexical stage |
47 self.token = self.tokens.__next__() | 49 self.token = self.tokens.__next__() |
50 def skipToSemi(self, tt): | |
51 while self.Peak != tt and self.Peak != 'END': | |
52 self.NextToken() | |
53 if self.Peak == tt: | |
54 self.Consume(tt) | |
48 | 55 |
49 def parsePackage(self): | 56 def parsePackage(self): |
50 self.Consume('package') | 57 self.Consume('package') |
51 name = self.Consume('ID') | 58 name = self.Consume('ID') |
52 self.Consume(';') | 59 self.Consume(';') |
170 | 177 |
171 def parseCompoundStatement(self): | 178 def parseCompoundStatement(self): |
172 self.Consume('{') | 179 self.Consume('{') |
173 statements = [] | 180 statements = [] |
174 while not self.hasConsumed('}'): | 181 while not self.hasConsumed('}'): |
175 statements.append(self.parseStatement()) | 182 s = self.parseStatement() |
183 if not type(s) is astnodes.EmptyStatement: | |
184 statements.append(s) | |
176 return astnodes.CompoundStatement(statements) | 185 return astnodes.CompoundStatement(statements) |
177 | 186 |
178 def parseStatement(self): | 187 def parseStatement(self): |
179 # Determine statement type based on the pending token: | 188 # Determine statement type based on the pending token: |
180 if self.Peak == 'if': | 189 if self.Peak == 'if': |
199 self.Error('Unable to determine statement') | 208 self.Error('Unable to determine statement') |
200 | 209 |
201 # Parsing expressions: | 210 # Parsing expressions: |
202 def parseExpression(self): | 211 def parseExpression(self): |
203 return self.parseBinopRhs(self.parsePrimary(), 0) | 212 return self.parseBinopRhs(self.parsePrimary(), 0) |
213 # TODO: use this error handling: | |
214 try: | |
215 return self.parseBinopRhs(self.parsePrimary(), 0) | |
216 except CompilerError as e: | |
217 self.diag.addDiag(e) | |
218 self.skipToSemi(';') | |
219 return astnodes.Literal(0) | |
204 def parsePrimary(self): | 220 def parsePrimary(self): |
205 if self.hasConsumed('('): | 221 if self.hasConsumed('('): |
206 e = self.parseExpression() | 222 e = self.parseExpression() |
207 self.Consume(')') | 223 self.Consume(')') |
208 return e | 224 return e |
210 val = self.Consume('NUMBER') | 226 val = self.Consume('NUMBER') |
211 return self.sema.actOnNumber(val.val, val.loc) | 227 return self.sema.actOnNumber(val.val, val.loc) |
212 elif self.Peak == 'REAL': | 228 elif self.Peak == 'REAL': |
213 val = self.Consume('REAL') | 229 val = self.Consume('REAL') |
214 return self.sema.actOnNumber(val.val, val.loc) | 230 return self.sema.actOnNumber(val.val, val.loc) |
231 elif self.Peak == 'true': | |
232 val = self.Consume('true') | |
233 return self.sema.actOnNumber(True, val.loc) | |
234 elif self.Peak == 'false': | |
235 val = self.Consume('false') | |
236 return self.sema.actOnNumber(False, val.loc) | |
215 elif self.Peak == 'ID': | 237 elif self.Peak == 'ID': |
216 d = self.parseDesignator() | 238 d = self.parseDesignator() |
217 if self.Peak == '(': | 239 if self.Peak == '(': |
218 return self.parseProcedureCall(d) | 240 return self.parseProcedureCall(d) |
219 else: | 241 else: |