def term(self): """ T -> F | F + T | F - T """ left = self.factor() peek = self.peek() if peek.token == "plus": plus = self.match("plus") right = self.term() return ast.ASTNode("plus_exp", plus, [left, right]) elif peek.token == "minus": minus = self.match("minus") right = self.term() return ast.ASTNode("minus_exp", minus, [left, right]) return left
def return_statement(self): """ R -> return E """ r = self.match("return") e = self.expr() self.match("semicolon") return ast.ASTNode("return", r, [e])
def var_decl_statement(self): """ Let -> let id = E; | let id: Ty; """ self.match("let") i = self.match("id") # let id = E if self.peek().token == "assign": self.match("assign") e = self.expr() self.match("semicolon") return ast.ASTNode("var_decl_assign", i, [e]) # let id: Ty self.match("colon") ty = self.type_decl() self.match("semicolon") return ast.ASTNode("var_decl", i, [ty])
def fn(self): self.match("function def") f = self.match("id") self.match("left paren") self.match("right paren") self.match("left brace") s = self.statement_list() self.match("right brace") return ast.ASTNode("main", f, [s])
def assign_statement(self): """ Ass -> id = E """ lhs = self.var() e = self.match("assign") ex = self.expr() self.match("semicolon") return ast.ASTNode("assignment", e, [lhs, ex])
def type_decl(self): """ Ty -> i32 | bool | <id> """ peek = self.peek() valid_type_tokens = ["i32", "bool", "id"] if peek.token in valid_type_tokens: t = self.match(peek.token) return ast.ASTNode(peek.token, t, None) self.error(f"Expected a type found: {peek}")
def statement_list(self): """ L -> S L | S assume all statement lists must end if next token is } """ statements = [] s = self.statement() statements.append(s) while self.peek().token != "right brace": statements.append(self.statement()) return ast.ASTNode("statement_list", s.symbol, statements)
def factor(self): """ F -> P | P * F """ left = self.paren() peek = self.peek() if peek.token == "times": times = self.match("times") right = self.factor() return ast.ASTNode("times_exp", times, [left, right]) return left
def expr(self): """ E -> T E -> T == T """ t = self.term() peek = self.peek() if peek.token == "equality": e = self.match("equality") t2 = self.term() return ast.ASTNode("equality_exp", e, [t, t2]) return t
def test_parse1(): prog = ["3 * (2 + 8) - 9 * 11;"] tokens = scanner.scan(prog, lexing_rules.RULES) p = parser.Parser(tokens) root = p.expr() a3 = ast.ASTNode("int_literal", scanner.Symbol("int literal", "3", 3, 1, 1), None) a2 = ast.ASTNode("int_literal", scanner.Symbol("int literal", "2", 2, 1, 6), None) a8 = ast.ASTNode("int_literal", scanner.Symbol("int literal", "8", 8, 1, 10), None) a9 = ast.ASTNode("int_literal", scanner.Symbol("int literal", "9", 9, 1, 15), None) a11 = ast.ASTNode("int_literal", scanner.Symbol("int literal", "11", 11, 1, 19), None) plus = ast.ASTNode("plus_exp", scanner.Symbol("plus", "+", None, 1, 8), [a2, a8]) times1 = ast.ASTNode("times_exp", scanner.Symbol("times", "*", None, 1, 3), [a3, plus]) times2 = ast.ASTNode("times_exp", scanner.Symbol("times", "*", None, 1, 17), [a9, a11]) minus = ast.ASTNode("minus_exp", scanner.Symbol("minus", "-", None, 1, 13), [times1, times2]) assert root == minus
def if_statement(self): """ If -> if (E) { L } | if (E) { L } else { L } """ i = self.match("if") self.match("left paren") e = self.expr() self.match("right paren") self.match("left brace") l1 = self.statement_list() self.match("right brace") if self.peek().token == "else": self.match("else") self.match("left brace") l2 = self.statement_list() self.match("right brace") # children are: # expression condition, if statement list, else statment list return ast.ASTNode("if_statement", i, [e, l1, l2]) # children are: # expression condition, if statement list return ast.ASTNode("if_statement", i, [e, l1])
def paren(self): """ P -> I | (E) | input | bool | Var """ peek = self.peek() if peek.token == "left paren": self.match("left paren") ex = self.term() self.match("right paren") return ex elif peek.token == "int literal": return self.int_literal() elif peek.token == "input": i = self.match("input") self.match("left paren") self.match("right paren") return ast.ASTNode("input_exp", i, None) elif peek.token == "bool_literal": return self.bool_literal() elif peek.token == "id": return self.var() self.error(f"unexpected {peek}")
def bool_literal(self): s = self.match("bool_literal") return ast.ASTNode("bool_literal", s, None)
def int_literal(self): sym = self.match("int literal") return ast.ASTNode("int_literal", sym, None)
def var(self): """ Var -> id """ i = self.match("id") return ast.ASTNode("var", i, None)