# -*- coding: utf-8 -*- from ast import * from lexer import * from token import * class Parser: def __init__(self, lex): self.lexer = lex self.token = lex.scan() self.count = 1 #debug return def parse(self): return self.program() def move(self): print self.count, self.token #debug self.count += 1 #debug self.token = self.lexer.scan() return def error(self, msg): raise Exception(msg) def match(self, tag): if self.token == None: self.error("Unexpected end of file.") if self.token.tag != tag: self.error("match: expected %s got %s\n" %(tag, self.token.tag)) val = self.token.value self.move() return val # boolean = join { "||" join }. def boolean(self): res = self.join() while self.token.tag == Tag.OPERATOR and self.token.value == "||": res = BinaryExpression(res, self.match(Tag.OPERATOR), self.join(), self.lexer.line) return res # join = relation { "&&" relation }. def join(self): res = self.relation() while self.token.tag == Tag.OPERATOR and self.token.value == "&&": res = BinaryExpression(res, self.match(Tag.OPERATOR), self.relation(), self.lexer.line) return res # relation = expression { ( "==" | "!=" | "<" | "<=" | ">=" | ">" ) expression }. def relation(self): res = self.expression() while self.token.tag == Tag.OPERATOR and self.token.value in ["==", "!=", "<", "<=", ">=", ">"]: res = BinaryExpression(res, self.match(Tag.OPERATOR), self.expression(), self.lexer.line) return res # expression = term { ( "+" | "-" ) term }. def expression(self): res = self.term() while self.token.tag == Tag.OPERATOR and self.token.value in ["+", "-"]: res = BinaryExpression(res, self.match(Tag.OPERATOR), self.term(), self.lexer.line) return res # term = unary { ( "*" | "/" | "%" ) unary }. def term(self): res = self.unary() while self.token.tag == Tag.OPERATOR and self.token.value in ["*", "/", "%"]: res = BinaryExpression(res, self.match(Tag.OPERATOR), self.unary(), self.lexer.line) return res # unary = "!" unary | "-" unary | factor. def unary(self): if self.token.tag == Tag.OPERATOR and self.token.value in ["!", "-"]: return UnaryExpression(self.match(Tag.OPERATOR), self.unary(), self.lexer.line) return self.factor() # factor = "(" boolean ")" | integer | "true" | "false" | ident | function_call. def factor(self): if self.token.tag == Tag.LPAREN: self.move() res = self.boolean() self.match(Tag.RPAREN) return res if self.token.tag == Tag.NUMBER: return Constant(self.match(Tag.NUMBER), self.lexer.line) if self.token.tag == Tag.TRUE: self.move() return Constant(1, self.lexer.line) if self.token.tag == Tag.FALSE: self.move() return Constant(0, self.lexer.line) if self.token.tag == Tag.IDENT: return Variable(self.match(Tag.IDENT), self.lexer.line) return self.function_call() # function_call = "call" ident "[" [ expression_list ] "]". def function_call(self): self.match(Tag.CALL) name = self.match(Tag.IDENT) self.match(Tag.LBRAK) args = [] if self.token.tag == Tag.RBRAK else self.expression_list() self.match(Tag.RBRAK) return FunctionCall(name, args, self.lexer.line) # ident_list = ident { "," ident }. def ident_list(self): ident = [self.match(Tag.IDENT)] while self.token.tag == Tag.COMMA: self.move() ident.append(self.match(Tag.IDENT)) return ident # expression_list = boolean { "," boolean }. def expression_list(self): exp = [self.boolean()] while self.token.tag == Tag.COMMA: self.move() exp.append(self.boolean()) return exp # function_list = function { function }. def function_list(self): funcs = [self.function()] while self.token: funcs.append(self.function()) return funcs # statement_list = statement { statement }. def statement_list(self): stat = [self.statement()] while self.token.tag not in [Tag.END, Tag.ELSE]: stat.append(self.statement()) return stat # function = "fun" ident "[" [ ident_list ] "]" nl statement_list "end" nl. def function(self): line = self.lexer.line self.match(Tag.FUN) name = self.match(Tag.IDENT) self.match(Tag.LBRAK) args = [] if self.token.tag == Tag.RBRAK else self.ident_list() self.match(Tag.RBRAK) self.match(Tag.NEWLINE) block = self.statement_list() self.match(Tag.END) self.match(Tag.NEWLINE) return Function(name, args, block, line) # statement = [ if_statement | while_statement | assign_statement | return_statement | function_call ]. def statement(self): return {Tag.IF: self.if_statement, Tag.WHILE: self.while_statement, Tag.IDENT: self.assignment, Tag.RETURN: self.return_statement, Tag.CALL: self.function_call, }[self.token.tag]() # if_statement = "if" boolean nl statement_list [ "else" nl statement_list ] "end" nl. def if_statement(self): line = self.lexer.line self.match(Tag.IF) condition = self.boolean() self.match(Tag.NEWLINE) true_case = self.statement_list() else_case = [] if self.token.tag == Tag.ELSE: self.move() self.match(Tag.NEWLINE) else_case = self.statement_list() self.match(Tag.END) self.match(Tag.NEWLINE) return IfStatement(condition, true_case, else_case, line) # while_statement = "while" boolean nl statement_list "end" nl. def while_statement(self): line = self.lexer.line self.match(Tag.WHILE) condition = self.boolean() self.match(Tag.NEWLINE) body = self.statement_list() self.match(Tag.END) self.match(Tag.NEWLINE) return WhileStatement(condition, body, line) # return_statement = "@" boolean nl. def return_statement(self): line = self.lexer.line self.match(Tag.RETURN) exp = self.boolean() self.match(Tag.NEWLINE) return ReturnStatement(exp, line) # assignment = ident "=" boolean nl. def assignment(self): line = self.lexer.line name = self.match(Tag.IDENT) self.match(Tag.ASSIGNMENT) exp = self.boolean() self.match(Tag.NEWLINE) return AssignStatement(name, exp, line) # program = function_list. def program(self): return Program(self.function_list())