comparison python/ppci/frontends/ks/parser.py @ 110:9e552d34bd60

Work on compiler
author Windel Bouwman
date Fri, 04 Jan 2013 15:25:58 +0100
parents f2d980eef509
children
comparison
equal deleted inserted replaced
108:8267ba1dbce3 110:9e552d34bd60
93 self.Consume(';') 93 self.Consume(';')
94 94
95 def parseImport(self): 95 def parseImport(self):
96 loc = self.getLocation() 96 loc = self.getLocation()
97 modname = self.Consume('ID') 97 modname = self.Consume('ID')
98 # TODO: fix
98 #mod = loadModule(modname) 99 #mod = loadModule(modname)
99 self.setLocation(mod, loc) 100 self.setLocation(mod, loc)
100 self.cst.addSymbol(mod) 101 self.cst.addSymbol(mod)
101 102
102 # Helper to parse an identifier defenitions 103 # Helper to parse an identifier defenitions
220 else: 221 else:
221 self.Error('Unimplemented unary operation {0}'.format(expr.op)) 222 self.Error('Unimplemented unary operation {0}'.format(expr.op))
222 else: 223 else:
223 self.Error('Cannot evaluate expression {0}'.format(expr)) 224 self.Error('Cannot evaluate expression {0}'.format(expr))
224 225
225 def parseConstExpression(self): 226 def parseConstant(self):
226 e = self.parseExpression() 227 e = self.parseExpression()
227 return self.evalExpression(e), e.typ 228 val = self.evalExpression(e)
229 return Constant(val, e.typ)
228 230
229 def parseConstantDeclarations(self): 231 def parseConstantDeclarations(self):
230 """ Parse const part of a module """ 232 """ Parse const part of a module """
231 if self.hasConsumed('const'): 233 if self.hasConsumed('const'):
232 while self.token.typ == 'ID': 234 while self.token.typ == 'ID':
233 i = self.parseIdentDef() 235 i = self.parseIdentDef()
234 self.Consume('=') 236 self.Consume('=')
235 constvalue, typ = self.parseConstExpression() 237 c = self.parseConstant()
236 self.Consume(';') 238 self.Consume(';')
237 c = Constant(constvalue, typ, name=i.name, public=i.ispublic) 239 c.name = i.name
240 c.public = i.ispublic
238 self.setLocation(c, i.location) 241 self.setLocation(c, i.location)
239 self.cst.addSymbol(c) 242 self.cst.addSymbol(c)
240 243
241 # Type system 244 # Type system
242 def parseTypeDeclarations(self): 245 def parseTypeDeclarations(self):
263 return self.parseStructuredType() 266 return self.parseStructuredType()
264 267
265 def parseStructuredType(self): 268 def parseStructuredType(self):
266 if self.hasConsumed('array'): 269 if self.hasConsumed('array'):
267 dimensions = [] 270 dimensions = []
268 dimensions.append( self.parseConstExpression() ) 271 dimensions.append( self.parseConstant() )
269 while self.hasConsumed(','): 272 while self.hasConsumed(','):
270 dimensions.append( self.parseConstExpression() ) 273 dimensions.append( self.parseConstant() )
271 self.Consume('of') 274 self.Consume('of')
272 arr = self.parseType() 275 arr = self.parseType()
273 for dimension, consttyp in reversed(dimensions): 276 for dimension in reversed(dimensions):
274 if not isType(consttyp, integer): 277 if not isType(dimension.typ, integer):
275 self.Error('array dimension must be an integer type (not {0})'.format(consttyp)) 278 self.Error('array dimension must be an integer type (not {0})'.format(consttyp))
276 if dimension < 2: 279 if dimension.value < 2:
277 self.Error('array dimension must be bigger than 1 (not {0})'.format(dimension)) 280 self.Error('array dimension must be bigger than 1 (not {0})'.format(dimension.value))
278 arr = ArrayType(dimension, arr) 281 arr = ArrayType(dimension.value, arr)
279 return arr 282 return arr
280 elif self.hasConsumed('record'): 283 elif self.hasConsumed('record'):
281 fields = {} 284 fields = {}
282 while self.token.typ == 'ID': 285 while self.token.typ == 'ID':
283 # parse a fieldlist: 286 # parse a fieldlist:
434 if self.token.typ != ')': 437 if self.token.typ != ')':
435 args = self.parseExpressionList() 438 args = self.parseExpressionList()
436 else: 439 else:
437 args = [] 440 args = []
438 self.Consume(')') 441 self.Consume(')')
442 # Type checking:
439 parameters = procedure.typ.parameters 443 parameters = procedure.typ.parameters
440 if len(args) != len(parameters): 444 if len(args) != len(parameters):
441 self.Error("Procedure requires {0} arguments, {1} given".format(len(parameters), len(args))) 445 self.Error("Procedure requires {0} arguments, {1} given".format(len(parameters), len(args)))
442 for arg, param in zip(args, parameters): 446 for arg, param in zip(args, parameters):
443 if not arg.typ.isType(param.typ): 447 if not arg.typ.isType(param.typ):
498 def parseRepeatStatement(self): 502 def parseRepeatStatement(self):
499 self.Consume('repeat') 503 self.Consume('repeat')
500 stmt = self.parseStatementSequence() 504 stmt = self.parseStatementSequence()
501 self.Consume('until') 505 self.Consume('until')
502 cond = self.parseBoolExpression() 506 cond = self.parseBoolExpression()
507 # TODO
503 508
504 def parseForStatement(self): 509 def parseForStatement(self):
505 loc = self.getLocation() 510 loc = self.getLocation()
506 self.Consume('for') 511 self.Consume('for')
507 variable = self.parseDesignator() 512 variable = self.parseDesignator()
515 self.Consume('to') 520 self.Consume('to')
516 end = self.parseExpression() 521 end = self.parseExpression()
517 if not end.typ.isType(integer): 522 if not end.typ.isType(integer):
518 self.Error('end expression of a for statement must have integer type') 523 self.Error('end expression of a for statement must have integer type')
519 if self.hasConsumed('by'): 524 if self.hasConsumed('by'):
520 increment, typ = self.parseConstExpression() 525 increment = self.parseConstant()
521 if not typ.isType(integer): 526 if not increment.typ.isType(integer):
522 self.Error('Increment must be integer') 527 self.Error('Increment must be integer')
528 increment = increment.value
523 else: 529 else:
524 increment = 1 530 increment = 1
525 assert(type(increment) is int) 531 assert(type(increment) is int)
526 self.Consume('do') 532 self.Consume('do')
527 statements = self.parseStatementSequence() 533 statements = self.parseStatementSequence()
528 self.Consume('end') 534 self.Consume('end')
529 return self.setLocation(ForStatement(variable, begin, end, increment, statements), loc) 535 return self.setLocation(ForStatement(variable, begin, end, increment, statements), loc)
530 536
531 def parseAsmcode(self): 537 def parseAsmcode(self):
532 # TODO: move this to seperate file 538 # TODO: move this to seperate file
539 # TODO: determine what to do with inline asm?
533 def parseOpcode(): 540 def parseOpcode():
534 return self.Consume('ID') 541 return self.Consume('ID')
535 def parseOperand(): 542 def parseOperand():
536 if self.hasConsumed('['): 543 if self.hasConsumed('['):
537 memref = [] 544 memref = []
605 self.Consume(self.token.typ) 612 self.Consume(self.token.typ)
606 return EmptyStatement() 613 return EmptyStatement()
607 614
608 def parseStatementSequence(self): 615 def parseStatementSequence(self):
609 """ Sequence of statements seperated by ';' """ 616 """ Sequence of statements seperated by ';' """
610 statements = [ self.parseStatement() ] 617 statements = [self.parseStatement()]
611 while self.hasConsumed(';'): 618 while self.hasConsumed(';'):
612 statements.append( self.parseStatement() ) 619 statements.append(self.parseStatement())
613 return StatementSequence( statements ) 620 return StatementSequence(statements)
614 621
615 # Parsing expressions: 622 # Parsing expressions:
616 """ 623 """
617 grammar of expressions: 624 grammar of expressions:
618 expression = SimpleExpression [ reloperator SimpleExpression ] 625 expression = SimpleExpression [ reloperator SimpleExpression ]
622 term = factor { muloperator factor } 629 term = factor { muloperator factor }
623 muloperator = '*' | '/' | 'div' | 'mod' | 'and' 630 muloperator = '*' | '/' | 'div' | 'mod' | 'and'
624 factor = number | nil | true | false | "(" expression ")" | 631 factor = number | nil | true | false | "(" expression ")" |
625 designator [ actualparameters ] | 'not' factor 632 designator [ actualparameters ] | 'not' factor
626 """ 633 """
634 def getTokenPrecedence(self):
635 binopPrecs = {}
636 binopPrecs['and'] = 8
637 binopPrecs['or'] = 6
638 binopPrecs['<'] = 10
639 binopPrecs['>'] = 10
640 binopPrecs['='] = 10
641 binopPrecs['<='] = 10
642 binopPrecs['>='] = 10
643 binopPrecs['<>'] = 10
644 binopPrecs['+'] = 20
645 binopPrecs['-'] = 20
646 binopPrecs['*'] = 40
647 binopPrecs['/'] = 40
648 binopPrecs['div'] = 40
649 binopPrecs['mod'] = 40
650
651 typ = self.token.typ
652 if typ in binopPrecs:
653 return binopPrecs[typ]
654 return 0
655 def parsePrimary(self):
656 pass
627 def parseExpression(self): 657 def parseExpression(self):
628 """ The connector between the boolean and expression domain """ 658 """ The connector between the boolean and expression domain """
659 # TODO: implement precedence bindin
660 #lhs = self.parsePrimary()
661 #return self.parseBinopRhs(lhs)
662
629 expr = self.parseSimpleExpression() 663 expr = self.parseSimpleExpression()
630 if self.token.typ in ['>=','<=','<','>','<>','=']: 664 if self.token.typ in ['>=','<=','<','>','<>','=']:
631 relop = self.Consume() 665 relop = self.Consume()
632 expr2 = self.parseSimpleExpression() 666 expr2 = self.parseSimpleExpression()
633 # Automatic type convert to reals: 667 # Automatic type convert to reals:
638 # Type check: 672 # Type check:
639 if not isType(expr.typ, expr2.typ): 673 if not isType(expr.typ, expr2.typ):
640 self.Error('Type mismatch in relop') 674 self.Error('Type mismatch in relop')
641 if isType(expr.typ, real) and relop in ['<>', '=']: 675 if isType(expr.typ, real) and relop in ['<>', '=']:
642 self.Error('Cannot check real values for equality') 676 self.Error('Cannot check real values for equality')
643
644 expr = Relop(expr, relop, expr2, boolean) 677 expr = Relop(expr, relop, expr2, boolean)
645 return expr 678 return expr
646 679
647 # Parsing arithmatic expressions: 680 # Parsing arithmatic expressions:
648 def parseTerm(self): 681 def parseTerm(self):
715 val = self.Consume('CHAR') 748 val = self.Consume('CHAR')
716 return Constant(val, char) 749 return Constant(val, char)
717 elif self.token.typ == 'STRING': 750 elif self.token.typ == 'STRING':
718 txt = self.Consume('STRING') 751 txt = self.Consume('STRING')
719 return StringConstant(txt) 752 return StringConstant(txt)
720 elif self.token.typ in ['true', 'false']: 753 elif self.hasConsumed('true'):
721 val = self.Consume() 754 return Constant(True, boolean)
722 val = True if val == 'true' else False 755 elif self.hasConsumed('false'):
723 return Constant(val, boolean) 756 return Constant(False, boolean)
724 elif self.hasConsumed('nil'): 757 elif self.hasConsumed('nil'):
725 return Constant(0, NilType()) 758 return Constant(0, NilType())
726 elif self.hasConsumed('not'): 759 elif self.hasConsumed('not'):
727 f = self.parseFactor() 760 f = self.parseFactor()
728 if not isType(f.typ, boolean): 761 if not isType(f.typ, boolean):