Files
pebble/src/ast/stmt.py

166 lines
3.7 KiB
Python

from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import TypeVar, Generic, Optional
from src.ast.expr import Expr
from src.token import Token
T = TypeVar("T")
@dataclass(frozen=True)
class Stmt(ABC):
@abstractmethod
def accept(self, visitor: Visitor[T]) -> T:
...
class Visitor(ABC, Generic[T]):
@abstractmethod
def visit_block_stmt(self, stmt: BlockStmt) -> T:
...
@abstractmethod
def visit_class_stmt(self, stmt: ClassStmt) -> T:
...
@abstractmethod
def visit_expression_stmt(self, stmt: ExpressionStmt) -> T:
...
@abstractmethod
def visit_function_stmt(self, stmt: FunctionStmt) -> T:
...
@abstractmethod
def visit_if_stmt(self, stmt: IfStmt) -> T:
...
@abstractmethod
def visit_return_stmt(self, stmt: ReturnStmt) -> T:
...
@abstractmethod
def visit_let_stmt(self, stmt: LetStmt) -> T:
...
@abstractmethod
def visit_while_stmt(self, stmt: WhileStmt) -> T:
...
@abstractmethod
def visit_for_stmt(self, stmt: ForStmt) -> T:
...
@abstractmethod
def visit_break_stmt(self, stmt: BreakStmt) -> T:
...
@abstractmethod
def visit_continue_stmt(self, stmt: ContinueStmt) -> T:
...
@dataclass(frozen=True)
class BlockStmt(Stmt):
statements: list[Stmt]
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_block_stmt(self)
@dataclass(frozen=True)
class ClassStmt(Stmt):
name: Token
methods: list[FunctionStmt]
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_class_stmt(self)
@dataclass(frozen=True)
class ExpressionStmt(Stmt):
expression: Expr
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_expression_stmt(self)
@dataclass(frozen=True)
class FunctionStmt(Stmt):
name: Token
params: list[Token]
body: list[Stmt]
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_function_stmt(self)
@dataclass(frozen=True)
class IfStmt(Stmt):
condition: Expr
then_branch: Stmt
else_branch: Optional[Stmt]
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_if_stmt(self)
@dataclass(frozen=True)
class ReturnStmt(Stmt):
keyword: Token
value: Optional[Expr]
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_return_stmt(self)
@dataclass(frozen=True)
class LetStmt(Stmt):
name: Token
initializer: Optional[Expr]
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_let_stmt(self)
@dataclass(frozen=True)
class WhileStmt(Stmt):
condition: Expr
body: Stmt
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_while_stmt(self)
@dataclass(frozen=True)
class ForStmt(Stmt):
variable: Token
start_token: Optional[Token]
start: Optional[Expr]
end_token: Optional[Token]
end: Optional[Expr]
step_token: Optional[Token]
step: Optional[Expr]
body: Stmt
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_for_stmt(self)
@dataclass(frozen=True)
class BreakStmt(Stmt):
keyword: Token
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_break_stmt(self)
@dataclass(frozen=True)
class ContinueStmt(Stmt):
keyword: Token
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_continue_stmt(self)