# -*- 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")