git @ Cat's Eye Technologies Dieter / master src / dieter / parser.py
master

Tree @master (Download .tar.gz)

parser.py @masterraw · history · blame

# -*- coding: utf-8 -*-

"""
parser.py -- parser for the Dieter programming language.
$Id: parser.py 382 2010-01-28 23:40:43Z cpressey $
"""

import dieter.ast as ast

class Parser(object):
    """
    A recursive-descent parser for Dieter.
    """

    def __init__(self, scanner):
        """
        Creates a new Parser object.  The passed-in scanner is expected
        to be compatible with a Scanner object.
        """
        self.scanner = scanner

    def Dieter(self):
        program = ast.Program()
        while self.scanner.token in ["order", "module", "forward"]:
            if self.scanner.token == "order":
                ordering = self.Ordering()
                program.add_ordering(ordering)
            elif self.scanner.token == "module":
                module = self.Module()
                program.add_module(module)
            elif self.scanner.token == "forward":
                forward = self.Forward()
                program.add_forward(forward)
            else:
                self.error("expected order, module or forward, found " +
                           self.scanner.token)
        return program

    def Ordering(self):
        self.scanner.expect("order")
        qual1 = self.scanner.grab()
        self.scanner.expect("<")
        qual2 = self.scanner.grab()
        ordering = ast.Ordering(qual1, qual2)
        return ordering

    def Module(self):
        self.scanner.expect("module")
        name = self.scanner.grab()
        fails = False
        if self.scanner.token == "fails":
            self.scanner.expect("fails")
            fails = True
        module = ast.Module(name, fails)
        while self.scanner.token == "var":
            self.scanner.expect("var")
            vdecl = self.VarDecl()
            module.add_local(vdecl)
        while self.scanner.token == "procedure":
            pdecl = self.ProcDecl()
            module.add_proc(pdecl)
        self.scanner.expect("end")
        return module

    def Forward(self):
        self.scanner.expect("forward")
        name = self.scanner.grab()
        type_expr = ast.ProcTypeExpr([], None)
        self.scanner.expect("(")
        if self.scanner.token != ")":
            arg_type_expr = self.TypeExpr()  
            type_expr.add_arg_type_expr(arg_type_expr)
            while self.scanner.token == ",":
                self.scanner.expect(",")
                arg_type_expr = self.TypeExpr()
                type_expr.add_arg_type_expr(arg_type_expr) 
        self.scanner.expect(")")
        self.scanner.expect(":")
        type_expr.return_type_expr = self.TypeExpr()
        fwd = ast.FwdDecl(name, type_expr)
        return fwd

    def VarDecl(self):
        name = self.scanner.grab()
        self.scanner.expect(":")
        type_expr = self.TypeExpr()
        var = ast.VarDecl(name, type_expr)
        return var

    def ProcDecl(self):
        self.scanner.expect("procedure")
        name = self.scanner.grab()
        proc = ast.ProcDecl(name)
        self.scanner.expect("(")
        if self.scanner.token != ")":
            arg = self.VarDecl()
            proc.add_arg(arg)
            while self.scanner.token == ",":
                self.scanner.expect(",")
                arg = self.VarDecl()
                proc.add_arg(arg)
        self.scanner.expect(")")
        self.scanner.expect(":")
        type_expr = self.TypeExpr()
        proc.set_return_type_expr(type_expr)
        while self.scanner.token == "var":
            self.scanner.expect("var")
            vdecl = self.VarDecl()
            proc.add_local(vdecl)
        stmt = self.Statement()
        proc.set_body(stmt)
        return proc

    def Statement(self):
        stmt = None
        if self.scanner.token == "begin":
            stmt = ast.CompoundStatement()
            self.scanner.expect("begin")
            while self.scanner.token != "end":
                step = self.Statement()
                stmt.add_step(step)
            self.scanner.expect("end")
        elif self.scanner.token == "if":
            self.scanner.expect("if")
            test = self.Expr()
            self.scanner.expect("then")
            then_stmt = self.Statement()
            else_stmt = None
            if self.scanner.token == "else":
                self.scanner.expect("else")
                else_stmt = self.Statement()
            stmt = ast.IfStatement(test, then_stmt, else_stmt)
        elif self.scanner.token == "while":
            self.scanner.expect("while")
            test = self.Expr()
            self.scanner.expect("do")
            body = self.Statement()
            stmt = ast.WhileStatement(test, body)
        elif self.scanner.token == "return":
            self.scanner.expect("return")
            if self.scanner.token == "final":
                self.scanner.expect("final")
            expr = self.Expr()
            stmt = ast.ReturnStatement(expr)
        else:
            name = self.scanner.grab()
            if self.scanner.token == "(":
                self.scanner.expect("(")
                stmt = ast.CallStatement(name)
                if self.scanner.token != ")":
                    expr = self.Expr()
                    stmt.add_arg(expr)
                    while self.scanner.token == ",":
                        self.scanner.expect(",")
                        expr = self.Expr()
                        stmt.add_arg(expr)
                self.scanner.expect(")")
            else:
                stmt = ast.AssignStatement(name)
                if self.scanner.token == "[":
                    self.scanner.expect("[")
                    index = self.Expr()
                    stmt.set_index(index)
                    self.scanner.expect("]")
                self.scanner.expect(":=")
                expr = self.Expr()
                stmt.set_expr(expr)
        return stmt

    def Expr(self):
        expr = None
        if self.scanner.token == "(":
            self.scanner.expect("(")
            expr = self.Expr()
            self.scanner.expect(")")
        elif self.scanner.token == "bestow":
            self.scanner.expect("bestow")
            name = self.scanner.grab()
            sub = self.Expr()
            expr = ast.BestowExpr(name, sub)
        elif self.scanner.token == "super":
            self.scanner.expect("super")
            expr = ast.SuperExpr()
        elif self.scanner.toktype == "int":
            value = self.scanner.tokval
            self.scanner.grab()
            expr = ast.IntConstExpr(value)
        elif self.scanner.toktype == "string":
            value = self.scanner.tokval
            self.scanner.grab()
            expr = ast.StringConstExpr(value)
        else:
            name = self.scanner.grab()
            if self.scanner.token == "(":
                expr = ast.CallExpr(name)
                self.scanner.expect("(")
                if self.scanner.token != ")":
                    sub = self.Expr()
                    expr.add_arg(sub)
                    while self.scanner.token == ",":
                        self.scanner.expect(",")
                        sub = self.Expr()
                        expr.add_arg(sub)
                self.scanner.expect(")")
            else:
                expr = ast.VarRefExpr(name)
                if self.scanner.token == "[":
                    self.scanner.expect("[")
                    index = self.Expr()
                    expr.set_index(index)
                    self.scanner.expect("]")
        return expr

    def TypeExpr(self):
        quals = []
        # XXX would be better to have 'forward qualifier'
        while self.scanner.token not in [
                u"void", u"bool", u"int", u"rat", u"string", u"ref", u"map", u"♥"
            ]:
            name = self.scanner.grab()
            quals.append(name)
        type_expr = self.BareTypeExpr()
        for qual in quals:
            type_expr = ast.QualifiedTypeExpr(qual, type_expr)
        return type_expr

    def BareTypeExpr(self):
        token = self.scanner.token
        if token in ["void", "bool", "int", "rat", "string","ref"]:
            self.scanner.scan()
            return ast.PrimitiveTypeExpr(token)
        elif token == "map":
            self.scanner.scan()
            from_type_expr = None
            if self.scanner.token == "from":
                self.scanner.expect("from")
                from_type_expr = self.TypeExpr()
            self.scanner.expect("to")
            to_type_expr = self.TypeExpr()
            return ast.MapTypeExpr(to_type_expr, from_type_expr)
        elif token == u"♥":
            self.scanner.scan()
            name = self.scanner.grab()
            return ast.TypeVariableExpr(name)
        else:
            self.scanner.error("expected valid type expression")