diff python/c3/parser.py @ 213:003c8a976fff

Merge of semantics and parser again ..
author Windel Bouwman
date Fri, 05 Jul 2013 11:18:48 +0200
parents 46d62dadd61b
children c1ccb1cb4cef
line wrap: on
line diff
--- a/python/c3/parser.py	Sun Jun 30 19:00:41 2013 +0200
+++ b/python/c3/parser.py	Fri Jul 05 11:18:48 2013 +0200
@@ -1,4 +1,4 @@
-from . import astnodes, lexer, semantics
+from . import astnodes, lexer
 from ppci import CompilerError
 
 # binop precedence for expressions:
@@ -7,140 +7,173 @@
    '+': 30, '-': 30, '*': 40, '/': 40 }
 
 class Parser:
-   """ Parses sourcecode into an abstract syntax tree (AST) """
-   def __init__(self, diag):
-      self.sema = semantics.Semantics(diag)
-      self.diag = diag
-   def parseSource(self, source):
+    """ Parses sourcecode into an abstract syntax tree (AST) """
+    def __init__(self, diag):
+        self.diag = diag
+
+    def parseSource(self, source):
       self.initLex(source)
-      self.sema.reinit()
       try:
          self.parsePackage()
-         return self.sema.mod
+         return self.mod
       except CompilerError as e:
          self.diag.addDiag(e)
-   def Error(self, msg):
+    def Error(self, msg):
       raise CompilerError(msg, self.token.loc)
-   # Lexer helpers:
-   def Consume(self, typ):
+    # Lexer helpers:
+    def Consume(self, typ):
       if self.Peak == typ:
          return self.NextToken()
       else:
          self.Error('Excected: "{0}", got "{1}"'.format(typ, self.Peak))
-   @property
-   def Peak(self):
+    @property
+    def Peak(self):
       return self.token.typ
-   @property
-   def PeakPrec(self):
+    @property
+    def PeakPrec(self):
       if self.Peak in binopPrecs:
          return binopPrecs[self.Peak]
       return -1
-   def hasConsumed(self, typ):
+    def hasConsumed(self, typ):
       if self.Peak == typ:
          self.Consume(typ)
          return True
       return False
-   def NextToken(self):
+
+    def NextToken(self):
       t = self.token
       if t.typ != 'END':
          self.token = self.tokens.__next__()
       return t
-   def initLex(self, source):
+
+    def initLex(self, source):
       self.tokens = lexer.tokenize(source) # Lexical stage
       self.token = self.tokens.__next__()
-   def skipToSemi(self, tt):
-      while self.Peak != tt and self.Peak != 'END':
-         self.NextToken()
-      if self.Peak == tt:
-         self.Consume(tt)
-      
-   def parsePackage(self):
+    
+    def parseUses(self):
+        pass
+
+    def parsePackage(self):
       self.Consume('package')
       name = self.Consume('ID')
       self.Consume(';')
-      self.sema.handlePackage(name.val, name.loc)
+      self.mod = astnodes.Package(name.val, name.loc)
+      self.parseUses()
       # TODO: parse uses
       while self.Peak != 'END':
          self.parseTopLevel()
       self.Consume('END')
 
-   def parseTopLevel(self):
+    def parseTopLevel(self):
       if self.Peak == 'function':
-         self.parseFunctionDefinition()
+         self.parseFunctionDef()
       elif self.Peak == 'var':
          self.parseVarDef()
       elif self.Peak == 'const':
          self.parseConstDef()
+      elif self.Peak == 'type':
+         self.parseTypeDef()
       else:
-         self.Error('Expected function or variable')
+         self.Error('Expected function, var, const or type')
 
-   def parseDesignator(self):
+    def parseDesignator(self):
       """ A designator designates an object """
       name = self.Consume('ID')
-      return self.sema.actOnDesignator(name.val, name.loc)
-
-   # Type system
-   def parseType(self):
-      d = self.parseDesignator()
+      d = astnodes.Designator(name.val, name.loc)
       return d
 
-   # Variable declarations:
-   def parseVarDef(self):
+    # Type system
+    def parseTypeSpec(self):
+        # For now, do simple type spec, just parse an ID:
+        return self.parseDesignator()
+        if self.Peak == 'struct':
+            self.Consume('struct')
+            self.Consume('{')
+            mems = []
+            while self.Peak != '}':
+                mem_t = self.parseTypeSpec()
+                mem_n = self.Consume('ID')
+                mems.append((mem_t, mem_n))
+                while self.hasConsumed(','):
+                    mem_n = self.Consume('ID')
+                    mems.append((mem_t, mem_n))
+                self.Consume(';')
+            self.Consume('}')
+            theT = astnodes.StructureType(mems)
+        else:
+            theT = self.parseDesignator()
+        # Check for pointer suffix:
+        while self.hasConsumed('*'):
+            theT = astnodes.PointerType(theT)
+        return theT
+
+    def parseTypeDef(self):
+        self.Consume('type')
+        newtype = self.parseTypeSpec()
+        typename = self.Consume('ID')
+        # TODO: action here :)
+        self.Consume(';')
+        return astnodes.DefinedType(typename, newtype)
+
+    # Variable declarations:
+    def parseVarDef(self):
       self.Consume('var')
-      t = self.parseType()
+      t = self.parseTypeSpec()
       def parseVar():
          name = self.Consume('ID')
-         ival = None
+         v = astnodes.Variable(name.val, t)
+         v.loc = name.loc
          if self.hasConsumed('='):
-            ival = self.parseExpression()
-         self.sema.actOnVarDef(name.val, name.loc, t, ival)
+            v.ival = self.parseExpression()
       parseVar()
       while self.hasConsumed(','):
          parseVar()
       self.Consume(';')
 
-   def parseConstDef(self):
+    def parseConstDef(self):
       self.Consume('const')
-      t = self.parseType()
+      t = self.parseTypeSpec()
       def parseConst():
          name = self.Consume('ID')
          self.Consume('=')
          val = self.parseExpression()
-         self.sema.actOnConstDef(name.val, name.loc, t, val)
+         c = astnodes.Constant(name.val, t, val)
+         c.loc = name.loc
       parseConst()
       while self.hasConsumed(','):
          parseConst()
       self.Consume(';')
       
-   # Procedures
-   def parseFunctionDefinition(self):
-      self.Consume('function')
-      returntype = self.parseType()
-      pname = self.Consume('ID')
-      self.sema.actOnFuncDef1(pname.val, pname.loc)
+    # Procedures
+    def parseFunctionDef(self):
+      loc = self.Consume('function').loc
+      returntype = self.parseTypeSpec()
+      fname = self.Consume('ID').val
+      f = astnodes.Function(fname, loc)
       self.Consume('(')
       parameters = []
       if not self.hasConsumed(')'):
          def parseParameter():
-            typ = self.parseType()
+            typ = self.parseTypeSpec()
             name = self.Consume('ID')
-            parameters.append(self.sema.actOnParameter(name.val, name.loc, typ))
+            param = astnodes.Variable(name.val, typ)
+            param.loc = name.loc
+            parameters.append(param)
          parseParameter()
          while self.hasConsumed(','):
             parseParameter()
          self.Consume(')')
       body = self.parseCompoundStatement()
-      self.sema.actOnFuncDef2(parameters, returntype, body)
 
-   # Statements:
-   def parseAssignment(self, lval):
-      lval = self.sema.actOnVariableUse(lval, lval.loc)
+    # Statements:
+    def parseAssignment(self, lval):
+      lval = astnodes.VariableUse(lval, lval.loc)
       loc = self.Consume('=').loc
       rval = self.parseExpression()
       self.Consume(';')
-      return self.sema.actOnAssignment(lval, rval, loc)
+      return astnodes.Assignment(lval, rval, loc)
 
-   def parseProcedureCall(self, func):
+    def parseCall(self, func):
       self.Consume('(')
       args = [] 
       if not self.hasConsumed(')'):
@@ -148,9 +181,9 @@
          while self.hasConsumed(','):
             args.append(self.parseExpression())
          self.Consume(')')
-      return self.sema.actOnFunctionCall(func, args, func.loc)
+      return astnodes.FunctionCall(func, args, func.loc)
 
-   def parseIfStatement(self):
+    def parseIfStatement(self):
       loc = self.Consume('if').loc
       self.Consume('(')
       condition = self.parseExpression()
@@ -160,23 +193,23 @@
          no = self.parseCompoundStatement()
       else:
          no = astnodes.EmptyStatement()
-      return self.sema.actOnIfStatement(condition, yes, no, loc)
+      return astnodes.IfStatement(condition, yes, no, loc)
 
-   def parseWhileStatement(self):
-      self.Consume('while')
+    def parseWhileStatement(self):
+      loc = self.Consume('while').loc
       self.Consume('(')
       condition = self.parseExpression()
       self.Consume(')')
       statements = self.parseCompoundStatement()
-      return astnodes.WhileStatement(condition, statements)
+      return astnodes.WhileStatement(condition, statements, loc)
 
-   def parseReturnStatement(self):
+    def parseReturnStatement(self):
       self.Consume('return')
       expr = self.parseExpression()
       self.Consume(';')
       return astnodes.ReturnStatement(expr)
 
-   def parseCompoundStatement(self):
+    def parseCompoundStatement(self):
       self.Consume('{')
       statements = []
       while not self.hasConsumed('}'):
@@ -185,7 +218,7 @@
             statements.append(s)
       return astnodes.CompoundStatement(statements)
 
-   def parseStatement(self):
+    def parseStatement(self):
       # Determine statement type based on the pending token:
       if self.Peak == 'if':
          return self.parseIfStatement()
@@ -200,49 +233,51 @@
          return astnodes.EmptyStatement()
       elif self.Peak == 'return':
          return self.parseReturnStatement()
-      elif self.Peak == 'ID':
+      else:
          designator = self.parseDesignator()
          if self.Peak == '(':
-            return self.parseProcedureCall(designator)
+            return self.parseCall(designator)
          elif self.Peak == '=':
             return self.parseAssignment(designator)
-      self.Error('Unable to determine statement')
+         else:
+              self.Error('Unable to determine statement')
 
-   # Parsing expressions:
-   def parseExpression(self):
+    # Parsing expressions:
+    def parseExpression(self):
       return self.parseBinopRhs(self.parsePrimary(), 0)
-   def parsePrimary(self):
+
+    def parsePrimary(self):
       if self.hasConsumed('('):
          e = self.parseExpression()
          self.Consume(')')
          return e
       elif self.Peak == 'NUMBER':
          val = self.Consume('NUMBER')
-         return self.sema.actOnNumber(val.val, val.loc)
+         return astnodes.Literal(val.val, val.loc)
       elif self.Peak == 'REAL':
          val = self.Consume('REAL')
-         return self.sema.actOnNumber(val.val, val.loc)
+         return astnodes.Literal(val.val, val.loc)
       elif self.Peak == 'true':
          val = self.Consume('true')
-         return self.sema.actOnNumber(True, val.loc)
+         return astnodes.Literal(True, val.loc)
       elif self.Peak == 'false':
          val = self.Consume('false')
-         return self.sema.actOnNumber(False, val.loc)
+         return astnodes.Literal(False, val.loc)
       elif self.Peak == 'ID':
          d = self.parseDesignator()
          if self.Peak == '(':
-            return self.parseProcedureCall(d)
+            return self.parseCall(d)
          else:
-            return self.sema.actOnVariableUse(d, d.loc)
+            return astnodes.VariableUse(d, d.loc)
       self.Error('Expected NUM, ID or (expr), got {0}'.format(self.Peak))
 
-   def parseBinopRhs(self, lhs, min_prec):
+    def parseBinopRhs(self, lhs, min_prec):
       while self.PeakPrec >= min_prec:
          op_prec = self.PeakPrec
          op = self.Consume(self.Peak)
          rhs = self.parsePrimary()
          while self.PeakPrec > op_prec:
             rhs = self.parseBinopRhs(rhs, self.PeakPrec)
-         lhs = self.sema.actOnBinop(lhs, op.typ, rhs, op.loc)
+         lhs = astnodes.Binop(lhs, op.typ, rhs, op.loc)
       return lhs