diff 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
line wrap: on
line diff
--- a/python/ppci/frontends/ks/parser.py	Tue Jan 01 17:17:44 2013 +0100
+++ b/python/ppci/frontends/ks/parser.py	Fri Jan 04 15:25:58 2013 +0100
@@ -95,6 +95,7 @@
    def parseImport(self):
       loc = self.getLocation()
       modname = self.Consume('ID')
+      # TODO: fix
       #mod = loadModule(modname)
       self.setLocation(mod, loc)
       self.cst.addSymbol(mod)
@@ -222,9 +223,10 @@
       else:
          self.Error('Cannot evaluate expression {0}'.format(expr))
 
-   def parseConstExpression(self):
+   def parseConstant(self):
       e = self.parseExpression()
-      return self.evalExpression(e), e.typ
+      val = self.evalExpression(e)
+      return Constant(val, e.typ)
 
    def parseConstantDeclarations(self):
       """ Parse const part of a module """
@@ -232,9 +234,10 @@
          while self.token.typ == 'ID':
             i = self.parseIdentDef()
             self.Consume('=')
-            constvalue, typ = self.parseConstExpression()
+            c = self.parseConstant()
             self.Consume(';')
-            c = Constant(constvalue, typ, name=i.name, public=i.ispublic)
+            c.name = i.name
+            c.public = i.ispublic
             self.setLocation(c, i.location)
             self.cst.addSymbol(c)
      
@@ -265,17 +268,17 @@
    def parseStructuredType(self):
       if self.hasConsumed('array'):
          dimensions = []
-         dimensions.append( self.parseConstExpression() )
+         dimensions.append( self.parseConstant() )
          while self.hasConsumed(','):
-             dimensions.append( self.parseConstExpression() )
+             dimensions.append( self.parseConstant() )
          self.Consume('of')
          arr = self.parseType()
-         for dimension, consttyp in reversed(dimensions):
-            if not isType(consttyp, integer):
+         for dimension in reversed(dimensions):
+            if not isType(dimension.typ, integer):
                self.Error('array dimension must be an integer type (not {0})'.format(consttyp))
-            if dimension < 2:
-               self.Error('array dimension must be bigger than 1 (not {0})'.format(dimension))
-            arr = ArrayType(dimension, arr)
+            if dimension.value < 2:
+               self.Error('array dimension must be bigger than 1 (not {0})'.format(dimension.value))
+            arr = ArrayType(dimension.value, arr)
          return arr
       elif self.hasConsumed('record'):
          fields = {}
@@ -436,6 +439,7 @@
       else:
          args = []
       self.Consume(')')
+      # Type checking:
       parameters = procedure.typ.parameters
       if len(args) != len(parameters):
          self.Error("Procedure requires {0} arguments, {1} given".format(len(parameters), len(args)))
@@ -500,6 +504,7 @@
       stmt = self.parseStatementSequence()
       self.Consume('until')
       cond = self.parseBoolExpression()
+      # TODO
 
    def parseForStatement(self):
       loc = self.getLocation()
@@ -517,9 +522,10 @@
       if not end.typ.isType(integer):
          self.Error('end expression of a for statement must have integer type')
       if self.hasConsumed('by'):
-         increment, typ = self.parseConstExpression()
-         if not typ.isType(integer):
+         increment = self.parseConstant()
+         if not increment.typ.isType(integer):
             self.Error('Increment must be integer')
+         increment = increment.value
       else:
          increment = 1
       assert(type(increment) is int)
@@ -530,6 +536,7 @@
 
    def parseAsmcode(self):
       # TODO: move this to seperate file
+      # TODO: determine what to do with inline asm?
       def parseOpcode():
          return self.Consume('ID')
       def parseOperand():
@@ -607,10 +614,10 @@
 
    def parseStatementSequence(self):
        """ Sequence of statements seperated by ';' """
-       statements = [ self.parseStatement() ]
+       statements = [self.parseStatement()]
        while self.hasConsumed(';'):
-         statements.append( self.parseStatement() )
-       return StatementSequence( statements )
+         statements.append(self.parseStatement())
+       return StatementSequence(statements)
 
    # Parsing expressions:
    """
@@ -624,8 +631,35 @@
      factor           = number | nil | true | false | "(" expression ")" | 
                         designator [ actualparameters ] | 'not' factor
    """
+   def getTokenPrecedence(self):
+      binopPrecs = {}
+      binopPrecs['and'] = 8
+      binopPrecs['or'] = 6
+      binopPrecs['<'] = 10
+      binopPrecs['>'] = 10
+      binopPrecs['='] = 10
+      binopPrecs['<='] = 10
+      binopPrecs['>='] = 10
+      binopPrecs['<>'] = 10
+      binopPrecs['+'] = 20
+      binopPrecs['-'] = 20
+      binopPrecs['*'] = 40
+      binopPrecs['/'] = 40
+      binopPrecs['div'] = 40
+      binopPrecs['mod'] = 40
+
+      typ = self.token.typ
+      if typ in binopPrecs:
+         return binopPrecs[typ]
+      return 0
+   def parsePrimary(self):
+      pass
    def parseExpression(self):
       """ The connector between the boolean and expression domain """
+      # TODO: implement precedence bindin
+      #lhs = self.parsePrimary()
+      #return self.parseBinopRhs(lhs)
+
       expr = self.parseSimpleExpression()
       if self.token.typ in ['>=','<=','<','>','<>','=']:
          relop = self.Consume()
@@ -640,7 +674,6 @@
             self.Error('Type mismatch in relop')
          if isType(expr.typ, real) and relop in ['<>', '=']:
             self.Error('Cannot check real values for equality')
-
          expr = Relop(expr, relop, expr2, boolean)
       return expr
 
@@ -717,10 +750,10 @@
       elif self.token.typ == 'STRING':
          txt = self.Consume('STRING')
          return StringConstant(txt)
-      elif self.token.typ in ['true', 'false']:
-         val = self.Consume()
-         val = True if val == 'true' else False
-         return Constant(val, boolean)
+      elif self.hasConsumed('true'):
+         return Constant(True, boolean)
+      elif self.hasConsumed('false'):
+         return Constant(False, boolean)
       elif self.hasConsumed('nil'):
          return Constant(0, NilType())
       elif self.hasConsumed('not'):