T Symbol String id Int lbp Int nud_bp Int led_bp (ASTNode -> ASTNode) nud ((ASTNode, ASTNode) -> ASTNode) led F set_nud_bp(nud_bp, nud) .nud_bp = nud_bp .nud = nud F set_led_bp(led_bp, led) .led_bp = led_bp .led = led T ASTNode Symbol& symbol Int value ASTNode? first_child ASTNode? second_child F eval() S .symbol.id ‘(number)’ R .value ‘+’ R .first_child.eval() + .second_child.eval() ‘-’ R I .second_child == N {-.first_child.eval()} E .first_child.eval() - .second_child.eval() ‘*’ R .first_child.eval() * .second_child.eval() ‘/’ R .first_child.eval() / .second_child.eval() ‘(’ R .first_child.eval() E assert(0B) R 0 [String = Symbol] symbol_table [String] tokens V tokeni = -1 ASTNode token_node F advance(sid = ‘’) I sid != ‘’ assert(:token_node.symbol.id == sid) :tokeni++ :token_node = ASTNode() I :tokeni == :tokens.len :token_node.symbol = :symbol_table[‘(end)’] R V token = :tokens[:tokeni] :token_node.symbol = :symbol_table[I token.is_digit() {‘(number)’} E token] I token.is_digit() :token_node.value = Int(token) F expression(rbp = 0) ASTNode t = move(:token_node) advance() V left = t.symbol.nud(move(t)) L rbp < :token_node.symbol.lbp t = move(:token_node) advance() left = t.symbol.led(t, move(left)) R left F parse(expr_str) -> ASTNode :tokens = re:‘\s*(\d+|.)’.find_strings(expr_str) :tokeni = -1 advance() R expression() F symbol(id, bp = 0) -> & I !(id C :symbol_table) V s = Symbol() s.id = id s.lbp = bp :symbol_table[id] = s R :symbol_table[id] F infix(id, bp) F led(ASTNode self, ASTNode left) self.first_child = left self.second_child = expression(self.symbol.led_bp) R self symbol(id, bp).set_led_bp(bp, led) F prefix(id, bp) F nud(ASTNode self) self.first_child = expression(self.symbol.nud_bp) R self symbol(id).set_nud_bp(bp, nud) infix(‘+’, 1) infix(‘-’, 1) infix(‘*’, 2) infix(‘/’, 2) prefix(‘-’, 3) F nud(ASTNode self) R self symbol(‘(number)’).nud = nud symbol(‘(end)’) F nud_parens(ASTNode self) V expr = expression() advance(‘)’) R expr symbol(‘(’).nud = nud_parens symbol(‘)’) L(expr_str) [‘-2 / 2 + 4 + 3 * 2’, ‘2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10’] print(expr_str‘ = ’parse(expr_str).eval())