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