diff 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
line wrap: on
line diff
--- a/python/c3/parser.py	Fri Mar 01 10:24:01 2013 +0100
+++ b/python/c3/parser.py	Fri Mar 01 11:43:52 2013 +0100
@@ -6,11 +6,6 @@
    '<': 20, '>': 20, '==': 20, '<=': 20, '>=': 20, '!=': 20, \
    '+': 30, '-': 30, '*': 40, '/': 40 }
 
-def getTokenPrecedence(typ):
-   if typ in binopPrecs:
-      return binopPrecs[typ]
-   return -1
-
 class Parser:
    """ Parses sourcecode into an abstract syntax tree (AST) """
    def __init__(self, sema, diag):
@@ -38,7 +33,9 @@
       return self.token.typ
    @property
    def PeakPrec(self):
-      return getTokenPrecedence(self.Peak)
+      if self.Peak in binopPrecs:
+         return binopPrecs[self.Peak]
+      return -1
    def hasConsumed(self, typ):
       if self.Peak == typ:
          self.Consume(typ)
@@ -64,16 +61,18 @@
       self.Consume('END')
 
    def parseTopLevel(self):
-      is_public = self.hasConsumed('public')
       if self.Peak == 'function':
-         self.parseFunctionDefinition(is_public)
+         self.parseFunctionDefinition()
       elif self.Peak == 'var':
-         self.parseVarDef(is_public)
+         self.parseVarDef()
+         self.Consume(';')
+      else:
+         self.Error('Expected function or variable')
 
    def parseDesignator(self):
       """ A designator designates an object """
       name = self.Consume('ID')
-      return name
+      return name.val
 
    # Type system
    def parseType(self):
@@ -81,19 +80,25 @@
       return d
 
    # Variable declarations:
-   def parseVarDef(self, is_public):
+   def parseVarDef(self):
       self.Consume('var')
-      typ = self.parseType()
-      ID = self.Consume('ID')
-      self.Consume(';')
-      v = Variable(i.name, typename, public=is_public)
-      self.curScope.add(v)
+      t = self.parseType()
+      def parseVar():
+         name = self.Consume('ID')
+         ival = None
+         if self.hasConsumed('='):
+            ival = self.parseExpression()
+         self.sema.actOnVarDef(name.val, name.loc, t, ival)
+      parseVar()
+      while self.hasConsumed(','):
+         parseVar()
 
    # Procedures
-   def parseFunctionDefinition(self, is_pub):
+   def parseFunctionDefinition(self):
       self.Consume('function')
       returntype = self.parseType()
-      procname = self.Consume('ID')
+      pname = self.Consume('ID')
+      self.sema.actOnFuncDef1(pname.val, pname.loc)
       self.Consume('(')
       parameters = []
       if not self.hasConsumed(')'):
@@ -105,9 +110,8 @@
             name = self.Consume('ID')
             parameters.append(astnodes.Parameter(name, typ))
          self.Consume(')')
-      proctyp = astnodes.FunctionType(parameters, returntype)
       body = self.parseCompoundStatement()
-      return astnodes.Procedure(procname, proctyp, body)
+      self.sema.actOnFuncDef2(parameters, returntype, body)
 
    # Statements:
    def parseAssignment(self, lval):
@@ -125,48 +129,37 @@
          self.Consume(')')
       return ProcedureCall(procedure, args)
 
-   def parseLocal(self, t):
-      name = self.Consume('ID')
-      if self.hasConsumed('='):
-         ival = self.parseExpression()
-      else:
-         ival = None
-      self.sema.actOnLocal(t, name, ival)
-   def parseLocalDeclaration(self):
-      self.Consume('var')
-      t = self.parseType()
-      self.parseLocal(t)
-      while self.hasConsumed(','):
-         self.parseLocal(t)
-
    def parseIfStatement(self):
       self.Consume('if')
       self.Consume('(')
       condition = self.parseExpression()
       self.Consume(')')
-      truestatement = self.parseStatement()
+      yes = self.parseCompoundStatement()
       if self.hasConsumed('else'):
-         els = self.parseStatement()
-         return astnodes.IfStatement(condition, truestatement, els)
-      return astnodes.IfStatement(condition, truestatement)
+         no = self.parseCompoundStatement()
+         return astnodes.IfStatement(condition, yes, no)
+      return astnodes.IfStatement(condition, yes)
 
    def parseWhileStatement(self):
       self.Consume('while')
       self.Consume('(')
       condition = self.parseExpression()
       self.Consume(')')
-      statements = self.parseStatement()
+      statements = self.parseCompoundStatement()
+      return astnodes.WhileStatement(condition, statements)
+
    def parseReturnStatement(self):
       self.Consume('return')
       expr = self.parseExpression()
+      return astnodes.ReturnStatement(expr)
 
    def parseCompoundStatement(self):
-       self.Consume('{')
-       statements = [self.parseStatement()]
-       while self.hasConsumed(';'):
+      self.Consume('{')
+      statements = [self.parseStatement()]
+      while self.hasConsumed(';'):
          statements.append(self.parseStatement())
-       self.Consume('}')
-       return astnodes.CompoundStatement(statements)
+      self.Consume('}')
+      return astnodes.CompoundStatement(statements)
 
    def parseStatement(self):
       # Determine statement type based on the pending token:
@@ -177,11 +170,10 @@
       elif self.Peak == '{':
          return self.parseCompoundStatement()
       elif self.Peak == 'var':
-         return self.parseLocalDeclaration()
+         return self.parseVarDef()
       elif self.Peak == 'return':
          return self.parseReturnStatement()
       elif self.Peak == 'ID':
-         # Assignment or procedure call
          designator = self.parseDesignator()
          if self.Peak == '(':
             return self.parseProcedureCall(designator)
@@ -199,7 +191,7 @@
          return e
       elif self.Peak == 'NUMBER':
          val = self.Consume('NUMBER')
-         return astnodes.Constant(val, val)
+         return self.sema.actOnNumber(val.val, val.loc)
       elif self.Peak == 'ID':
          d = self.parseDesignator()
          return d
@@ -212,6 +204,6 @@
          rhs = self.parsePrimary()
          while self.PeakPrec > op_prec:
             rhs = self.parseBinopRhs(rhs, self.PeakPrec)
-         lhs = astnodes.Binop(lhs, op, rhs)
+         lhs = self.sema.actOnBinop(lhs, op.typ, rhs, op.loc)
       return lhs