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.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
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)