comparison python/c3/parser.py @ 149:74241ca312cc

Fixes on parser and semantics
author Windel Bouwman
date Fri, 01 Mar 2013 11:43:52 +0100
parents e5263f74b287
children 4ae0e02599de
comparison
equal deleted inserted replaced
148:e5263f74b287 149:74241ca312cc
3 3
4 # binop precedence for expressions: 4 # binop precedence for expressions:
5 binopPrecs = {'or': 5, 'and': 10, \ 5 binopPrecs = {'or': 5, 'and': 10, \
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
9 def getTokenPrecedence(typ):
10 if typ in binopPrecs:
11 return binopPrecs[typ]
12 return -1
13 8
14 class Parser: 9 class Parser:
15 """ Parses sourcecode into an abstract syntax tree (AST) """ 10 """ Parses sourcecode into an abstract syntax tree (AST) """
16 def __init__(self, sema, diag): 11 def __init__(self, sema, diag):
17 self.sema = sema 12 self.sema = sema
36 @property 31 @property
37 def Peak(self): 32 def Peak(self):
38 return self.token.typ 33 return self.token.typ
39 @property 34 @property
40 def PeakPrec(self): 35 def PeakPrec(self):
41 return getTokenPrecedence(self.Peak) 36 if self.Peak in binopPrecs:
37 return binopPrecs[self.Peak]
38 return -1
42 def hasConsumed(self, typ): 39 def hasConsumed(self, typ):
43 if self.Peak == typ: 40 if self.Peak == typ:
44 self.Consume(typ) 41 self.Consume(typ)
45 return True 42 return True
46 return False 43 return False
62 while self.Peak != 'END': 59 while self.Peak != 'END':
63 self.parseTopLevel() 60 self.parseTopLevel()
64 self.Consume('END') 61 self.Consume('END')
65 62
66 def parseTopLevel(self): 63 def parseTopLevel(self):
67 is_public = self.hasConsumed('public')
68 if self.Peak == 'function': 64 if self.Peak == 'function':
69 self.parseFunctionDefinition(is_public) 65 self.parseFunctionDefinition()
70 elif self.Peak == 'var': 66 elif self.Peak == 'var':
71 self.parseVarDef(is_public) 67 self.parseVarDef()
68 self.Consume(';')
69 else:
70 self.Error('Expected function or variable')
72 71
73 def parseDesignator(self): 72 def parseDesignator(self):
74 """ A designator designates an object """ 73 """ A designator designates an object """
75 name = self.Consume('ID') 74 name = self.Consume('ID')
76 return name 75 return name.val
77 76
78 # Type system 77 # Type system
79 def parseType(self): 78 def parseType(self):
80 d = self.parseDesignator() 79 d = self.parseDesignator()
81 return d 80 return d
82 81
83 # Variable declarations: 82 # Variable declarations:
84 def parseVarDef(self, is_public): 83 def parseVarDef(self):
85 self.Consume('var') 84 self.Consume('var')
86 typ = self.parseType() 85 t = self.parseType()
87 ID = self.Consume('ID') 86 def parseVar():
88 self.Consume(';') 87 name = self.Consume('ID')
89 v = Variable(i.name, typename, public=is_public) 88 ival = None
90 self.curScope.add(v) 89 if self.hasConsumed('='):
90 ival = self.parseExpression()
91 self.sema.actOnVarDef(name.val, name.loc, t, ival)
92 parseVar()
93 while self.hasConsumed(','):
94 parseVar()
91 95
92 # Procedures 96 # Procedures
93 def parseFunctionDefinition(self, is_pub): 97 def parseFunctionDefinition(self):
94 self.Consume('function') 98 self.Consume('function')
95 returntype = self.parseType() 99 returntype = self.parseType()
96 procname = self.Consume('ID') 100 pname = self.Consume('ID')
101 self.sema.actOnFuncDef1(pname.val, pname.loc)
97 self.Consume('(') 102 self.Consume('(')
98 parameters = [] 103 parameters = []
99 if not self.hasConsumed(')'): 104 if not self.hasConsumed(')'):
100 typ = self.parseType() 105 typ = self.parseType()
101 name = self.Consume('ID') 106 name = self.Consume('ID')
103 while self.hasConsumed(','): 108 while self.hasConsumed(','):
104 typ = self.parseType() 109 typ = self.parseType()
105 name = self.Consume('ID') 110 name = self.Consume('ID')
106 parameters.append(astnodes.Parameter(name, typ)) 111 parameters.append(astnodes.Parameter(name, typ))
107 self.Consume(')') 112 self.Consume(')')
108 proctyp = astnodes.FunctionType(parameters, returntype)
109 body = self.parseCompoundStatement() 113 body = self.parseCompoundStatement()
110 return astnodes.Procedure(procname, proctyp, body) 114 self.sema.actOnFuncDef2(parameters, returntype, body)
111 115
112 # Statements: 116 # Statements:
113 def parseAssignment(self, lval): 117 def parseAssignment(self, lval):
114 self.Consume('=') 118 self.Consume('=')
115 rval = self.parseExpression() 119 rval = self.parseExpression()
123 while self.hasConsumed(','): 127 while self.hasConsumed(','):
124 args.append(self.parseExpression()) 128 args.append(self.parseExpression())
125 self.Consume(')') 129 self.Consume(')')
126 return ProcedureCall(procedure, args) 130 return ProcedureCall(procedure, args)
127 131
128 def parseLocal(self, t):
129 name = self.Consume('ID')
130 if self.hasConsumed('='):
131 ival = self.parseExpression()
132 else:
133 ival = None
134 self.sema.actOnLocal(t, name, ival)
135 def parseLocalDeclaration(self):
136 self.Consume('var')
137 t = self.parseType()
138 self.parseLocal(t)
139 while self.hasConsumed(','):
140 self.parseLocal(t)
141
142 def parseIfStatement(self): 132 def parseIfStatement(self):
143 self.Consume('if') 133 self.Consume('if')
144 self.Consume('(') 134 self.Consume('(')
145 condition = self.parseExpression() 135 condition = self.parseExpression()
146 self.Consume(')') 136 self.Consume(')')
147 truestatement = self.parseStatement() 137 yes = self.parseCompoundStatement()
148 if self.hasConsumed('else'): 138 if self.hasConsumed('else'):
149 els = self.parseStatement() 139 no = self.parseCompoundStatement()
150 return astnodes.IfStatement(condition, truestatement, els) 140 return astnodes.IfStatement(condition, yes, no)
151 return astnodes.IfStatement(condition, truestatement) 141 return astnodes.IfStatement(condition, yes)
152 142
153 def parseWhileStatement(self): 143 def parseWhileStatement(self):
154 self.Consume('while') 144 self.Consume('while')
155 self.Consume('(') 145 self.Consume('(')
156 condition = self.parseExpression() 146 condition = self.parseExpression()
157 self.Consume(')') 147 self.Consume(')')
158 statements = self.parseStatement() 148 statements = self.parseCompoundStatement()
149 return astnodes.WhileStatement(condition, statements)
150
159 def parseReturnStatement(self): 151 def parseReturnStatement(self):
160 self.Consume('return') 152 self.Consume('return')
161 expr = self.parseExpression() 153 expr = self.parseExpression()
154 return astnodes.ReturnStatement(expr)
162 155
163 def parseCompoundStatement(self): 156 def parseCompoundStatement(self):
164 self.Consume('{') 157 self.Consume('{')
165 statements = [self.parseStatement()] 158 statements = [self.parseStatement()]
166 while self.hasConsumed(';'): 159 while self.hasConsumed(';'):
167 statements.append(self.parseStatement()) 160 statements.append(self.parseStatement())
168 self.Consume('}') 161 self.Consume('}')
169 return astnodes.CompoundStatement(statements) 162 return astnodes.CompoundStatement(statements)
170 163
171 def parseStatement(self): 164 def parseStatement(self):
172 # Determine statement type based on the pending token: 165 # Determine statement type based on the pending token:
173 if self.Peak == 'if': 166 if self.Peak == 'if':
174 return self.parseIfStatement() 167 return self.parseIfStatement()
175 elif self.Peak == 'while': 168 elif self.Peak == 'while':
176 return self.parseWhileStatement() 169 return self.parseWhileStatement()
177 elif self.Peak == '{': 170 elif self.Peak == '{':
178 return self.parseCompoundStatement() 171 return self.parseCompoundStatement()
179 elif self.Peak == 'var': 172 elif self.Peak == 'var':
180 return self.parseLocalDeclaration() 173 return self.parseVarDef()
181 elif self.Peak == 'return': 174 elif self.Peak == 'return':
182 return self.parseReturnStatement() 175 return self.parseReturnStatement()
183 elif self.Peak == 'ID': 176 elif self.Peak == 'ID':
184 # Assignment or procedure call
185 designator = self.parseDesignator() 177 designator = self.parseDesignator()
186 if self.Peak == '(': 178 if self.Peak == '(':
187 return self.parseProcedureCall(designator) 179 return self.parseProcedureCall(designator)
188 elif self.Peak == '=': 180 elif self.Peak == '=':
189 return self.parseAssignment(designator) 181 return self.parseAssignment(designator)
197 e = self.parseExpression() 189 e = self.parseExpression()
198 self.Consume(')') 190 self.Consume(')')
199 return e 191 return e
200 elif self.Peak == 'NUMBER': 192 elif self.Peak == 'NUMBER':
201 val = self.Consume('NUMBER') 193 val = self.Consume('NUMBER')
202 return astnodes.Constant(val, val) 194 return self.sema.actOnNumber(val.val, val.loc)
203 elif self.Peak == 'ID': 195 elif self.Peak == 'ID':
204 d = self.parseDesignator() 196 d = self.parseDesignator()
205 return d 197 return d
206 self.Error('Expected NUM, ID or (expr), got {0}'.format(self.Peak)) 198 self.Error('Expected NUM, ID or (expr), got {0}'.format(self.Peak))
207 199
210 op_prec = self.PeakPrec 202 op_prec = self.PeakPrec
211 op = self.Consume(self.Peak) 203 op = self.Consume(self.Peak)
212 rhs = self.parsePrimary() 204 rhs = self.parsePrimary()
213 while self.PeakPrec > op_prec: 205 while self.PeakPrec > op_prec:
214 rhs = self.parseBinopRhs(rhs, self.PeakPrec) 206 rhs = self.parseBinopRhs(rhs, self.PeakPrec)
215 lhs = astnodes.Binop(lhs, op, rhs) 207 lhs = self.sema.actOnBinop(lhs, op.typ, rhs, op.loc)
216 return lhs 208 return lhs
217 209