Skip to content

Commit

Permalink
chapter 5: challenge 3 done
Browse files Browse the repository at this point in the history
  • Loading branch information
BaLiKfromUA committed May 6, 2023
1 parent 7e5f8fa commit 1818796
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
21 changes: 21 additions & 0 deletions pylox/util/rpn_ast_printer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pylox.expr as ast


# Define a visitor class for our syntax tree classes that takes an expression,
# converts it to RPN, and returns the resulting string.
class RpnAstPrinter(ast.ExprVisitor):

def print_expr(self, expr: ast.Expr):
return expr.accept(self)

def visit_binary_expr(self, expr: ast.Binary):
return f'{str(expr.left.accept(self))} {str(expr.right.accept(self))} {expr.operator.lexeme}'

def visit_grouping_expr(self, expr: ast.Grouping):
return expr.expr.accept(self)

def visit_literal_expr(self, expr: ast.Literal):
return str(expr.value)

def visit_unary_expr(self, expr: ast.Unary):
return f'{str(expr.right.accept(self))} {expr.operator.lexeme}'
23 changes: 23 additions & 0 deletions tests/test_ast.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from pylox.util.ast_printer import AstPrinter
from pylox.util.rpn_ast_printer import RpnAstPrinter
from pylox.scanner import Token, TokenType
import pylox.expr as ast


# example from http://www.craftinginterpreters.com/representing-code.html#a-not-very-pretty-printer
def test_if_ast_printer_works_correct() -> None:
# GIVEN
# -123 * (45.67)
expression = ast.Binary(
ast.Unary(
Token(TokenType.MINUS, "-", None, 1),
Expand All @@ -18,3 +20,24 @@ def test_if_ast_printer_works_correct() -> None:

# THEN
assert result == "(* (- 123) (group 45.67))"


# challenge 3 from http://www.craftinginterpreters.com/representing-code.html#challenges
def test_if_rpn_ast_printer_works_correct() -> None:
# GIVEN
# (1 + 2) * (4 - 3)
expression = ast.Binary(
ast.Grouping(
ast.Binary(ast.Literal(1),
Token(TokenType.PLUS, "+", None, 1),
ast.Literal(2))),
Token(TokenType.STAR, "*", None, 1),
ast.Grouping(
ast.Binary(ast.Literal(4),
Token(TokenType.MINUS, "-", None, 1),
ast.Literal(3)))
)
# WHEN
result = RpnAstPrinter().print_expr(expression)
# THEN
assert result == "1 2 + 4 3 - *"
7 changes: 5 additions & 2 deletions tools/generate_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ def define_ast(base_name, types):
# TODO: Add output directory handling
path = "../pylox/" + base_name.lower() + ".py"
file = open(path, "w")

# HEADER
file.write("# THIS CODE IS GENERATED AUTOMATICALLY. DO NOT CHANGE IT MANUALLY!\n\n")

# IMPORTS
file.write('import typing\n')
file.write('from abc import ABC, abstractmethod\n\n')
file.write('from pylox.tokens import Token\n')
# VISITOR
define_visitor(file, base_name, types)
# BASE CLASS
file.write(f'class {base_name}:\n')
file.write(f'{TAB}def __init__(self):\n')
file.write(f'{TAB * 2}pass\n')
file.write(f'{TAB}@abstractmethod\n')
file.write(f'{TAB}def accept(self, visitor : {base_name}Visitor):\n')
file.write(f'{TAB * 2}pass')
file.write('\n')
# IMPLEMENTATIONS
for className, fields in types.items():
file.write('\n')
define_type(file, base_name, className, fields)
Expand Down

0 comments on commit 1818796

Please sign in to comment.