calculator: add initial AST implementation
The AST's class hierarchy is defined inside the `calculator.ast` module. An abstract visitor is defined inside the `calculator.ast.visit` package.
This commit is contained in:
parent
e7c70bd6a5
commit
5ea82de840
1
calculator/calculator/__init__.py
Normal file
1
calculator/calculator/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import calculator.ast
|
4
calculator/calculator/ast/__init__.py
Normal file
4
calculator/calculator/ast/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from .node import Node # isort:skip
|
||||||
|
from .binop import BinOp
|
||||||
|
from .constant import Constant
|
||||||
|
from .unaryop import UnaryOp
|
28
calculator/calculator/ast/binop.py
Normal file
28
calculator/calculator/ast/binop.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
|
from pydantic.dataclasses import dataclass
|
||||||
|
|
||||||
|
from .node import Node
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from calculator.ast.visit import Visitor
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(config=Config)
|
||||||
|
class BinOp(Node):
|
||||||
|
"""
|
||||||
|
Node to represent a binary operation
|
||||||
|
"""
|
||||||
|
|
||||||
|
op: Callable[[int, int], int]
|
||||||
|
lhs: Node
|
||||||
|
rhs: Node
|
||||||
|
|
||||||
|
def accept(self, v: Visitor) -> None:
|
||||||
|
v.visit_binop(self)
|
26
calculator/calculator/ast/constant.py
Normal file
26
calculator/calculator/ast/constant.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from pydantic.dataclasses import dataclass
|
||||||
|
|
||||||
|
from .node import Node
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from calculator.ast.visit import Visitor
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(config=Config)
|
||||||
|
class Constant(Node):
|
||||||
|
"""
|
||||||
|
Node to represent a constant value.
|
||||||
|
"""
|
||||||
|
|
||||||
|
value: int
|
||||||
|
|
||||||
|
def accept(self, v: Visitor) -> None:
|
||||||
|
v.visit_constant(self)
|
17
calculator/calculator/ast/node.py
Normal file
17
calculator/calculator/ast/node.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from calculator.ast.visit import Visitor
|
||||||
|
|
||||||
|
|
||||||
|
class Node(ABC):
|
||||||
|
"""
|
||||||
|
Abstract Node class for calculator AST.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def accept(self, v: Visitor) -> None:
|
||||||
|
pass
|
27
calculator/calculator/ast/unaryop.py
Normal file
27
calculator/calculator/ast/unaryop.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
|
from pydantic.dataclasses import dataclass
|
||||||
|
|
||||||
|
from .node import Node
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from calculator.ast.visit import Visitor
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(config=Config)
|
||||||
|
class UnaryOp(Node):
|
||||||
|
"""
|
||||||
|
Node to represent a unary operation
|
||||||
|
"""
|
||||||
|
|
||||||
|
op: Callable[[int], int]
|
||||||
|
rhs: Node
|
||||||
|
|
||||||
|
def accept(self, v: Visitor) -> None:
|
||||||
|
v.visit_unaryop(self)
|
1
calculator/calculator/ast/visit/__init__.py
Normal file
1
calculator/calculator/ast/visit/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from .visitor import Visitor # isort:skip
|
28
calculator/calculator/ast/visit/visitor.py
Normal file
28
calculator/calculator/ast/visit/visitor.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from calculator.ast import BinOp, Constant, Node, UnaryOp
|
||||||
|
|
||||||
|
|
||||||
|
class Visitor(ABC):
|
||||||
|
"""
|
||||||
|
Abstract Visitor class for the AST class hierarchy.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def visit(self, n: Node) -> None:
|
||||||
|
n.accept(self)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_constant(self, c: Constant) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_binop(self, b: BinOp) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_unaryop(self, b: UnaryOp) -> None:
|
||||||
|
pass
|
Loading…
Reference in a new issue