feat(ast): add basic AST expressions and printer
This commit is contained in:
16
main.py
16
main.py
@@ -1,5 +1,7 @@
|
|||||||
|
from src.ast.expr import Expr, BinaryExpr, UnaryExpr, LiteralExpr, GroupingExpr
|
||||||
|
from src.ast.printer import AstPrinter
|
||||||
from src.lexer import Lexer
|
from src.lexer import Lexer
|
||||||
from src.token import Token
|
from src.token import Token, TokenType
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -17,5 +19,17 @@ def main():
|
|||||||
tokens: list[Token] = lexer.process(source, path)
|
tokens: list[Token] = lexer.process(source, path)
|
||||||
print(tokens)
|
print(tokens)
|
||||||
|
|
||||||
|
printer: AstPrinter = AstPrinter()
|
||||||
|
ast: Expr = BinaryExpr(
|
||||||
|
UnaryExpr(
|
||||||
|
Token(TokenType.MINUS, "-", None, None),
|
||||||
|
LiteralExpr(123)
|
||||||
|
),
|
||||||
|
Token(TokenType.STAR, "*", None, None),
|
||||||
|
GroupingExpr(LiteralExpr(45.67))
|
||||||
|
)
|
||||||
|
print(printer.print(ast))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
0
src/ast/__init__.py
Normal file
0
src/ast/__init__.py
Normal file
70
src/ast/expr.py
Normal file
70
src/ast/expr.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, TypeVar, Generic
|
||||||
|
|
||||||
|
from src.token import Token
|
||||||
|
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Expr(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def accept(self, visitor: Visitor[T]) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Visitor(ABC, Generic[T]):
|
||||||
|
@abstractmethod
|
||||||
|
def visit_binary_expr(self, expr: BinaryExpr) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_unary_expr(self, expr: UnaryExpr) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_grouping_expr(self, expr: GroupingExpr) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_literal_expr(self, expr: LiteralExpr) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class BinaryExpr(Expr):
|
||||||
|
left: Expr
|
||||||
|
operator: Token
|
||||||
|
right: Expr
|
||||||
|
|
||||||
|
def accept(self, visitor: Visitor[T]) -> T:
|
||||||
|
return visitor.visit_binary_expr(self)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class UnaryExpr(Expr):
|
||||||
|
operator: Token
|
||||||
|
right: Expr
|
||||||
|
|
||||||
|
def accept(self, visitor: Visitor[T]) -> T:
|
||||||
|
return visitor.visit_unary_expr(self)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class GroupingExpr(Expr):
|
||||||
|
expression: Expr
|
||||||
|
|
||||||
|
def accept(self, visitor: Visitor[T]) -> T:
|
||||||
|
return visitor.visit_grouping_expr(self)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class LiteralExpr(Expr):
|
||||||
|
value: Any
|
||||||
|
|
||||||
|
def accept(self, visitor: Visitor[T]) -> T:
|
||||||
|
return visitor.visit_literal_expr(self)
|
||||||
21
src/ast/printer.py
Normal file
21
src/ast/printer.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from src.ast.expr import Visitor, Expr, LiteralExpr, T, GroupingExpr, UnaryExpr, BinaryExpr
|
||||||
|
|
||||||
|
|
||||||
|
class AstPrinter(Visitor[str]):
|
||||||
|
def print(self, expr: Expr):
|
||||||
|
return expr.accept(self)
|
||||||
|
|
||||||
|
def parenthesize(self, name: str, *expressions: Expr):
|
||||||
|
return f"({name} {' '.join(expr.accept(self) for expr in expressions)})"
|
||||||
|
|
||||||
|
def visit_binary_expr(self, expr: BinaryExpr) -> str:
|
||||||
|
return self.parenthesize(expr.operator.lexeme, expr.left, expr.right)
|
||||||
|
|
||||||
|
def visit_unary_expr(self, expr: UnaryExpr) -> str:
|
||||||
|
return self.parenthesize(expr.operator.lexeme, expr.right)
|
||||||
|
|
||||||
|
def visit_grouping_expr(self, expr: GroupingExpr) -> str:
|
||||||
|
return self.parenthesize("group", expr.expression)
|
||||||
|
|
||||||
|
def visit_literal_expr(self, expr: LiteralExpr) -> str:
|
||||||
|
return str(expr.value)
|
||||||
Reference in New Issue
Block a user