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: