Mercurial > lcfOS
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 |