feat(ast): add basic AST expressions and printer

This commit is contained in:
2026-02-05 13:55:07 +01:00
parent 767e55a059
commit 51eb540b3c
4 changed files with 106 additions and 1 deletions

16
main.py
View File

@@ -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.token import Token
from src.token import Token, TokenType
def main():
@@ -17,5 +19,17 @@ def main():
tokens: list[Token] = lexer.process(source, path)
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__':
main()

0
src/ast/__init__.py Normal file
View File

70
src/ast/expr.py Normal file
View 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
View 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)