fix(parser): update AST printer
This commit is contained in:
@@ -38,8 +38,8 @@ class AstPrinter(Generic[T]):
|
|||||||
return self._buf.getvalue()
|
return self._buf.getvalue()
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def _child_level(self, last: bool = False) -> Generator[None, None, None]:
|
def _child_level(self, single: bool = False) -> Generator[None, None, None]:
|
||||||
self._levels.append(_Level.LAST if last else _Level.ACTIVE)
|
self._levels.append(_Level.LAST if single else _Level.ACTIVE)
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
@@ -79,108 +79,169 @@ class AstPrinter(Generic[T]):
|
|||||||
self._write_line(f"{label}: None")
|
self._write_line(f"{label}: None")
|
||||||
else:
|
else:
|
||||||
self._write_line(label)
|
self._write_line(label)
|
||||||
with self._child_level(last=True):
|
with self._child_level(single=True):
|
||||||
child.accept(self)
|
child.accept(self)
|
||||||
|
|
||||||
|
|
||||||
class MidasAstPrinter(AstPrinter, m.Expr.Visitor[None], m.Stmt.Visitor[None]):
|
class MidasAstPrinter(AstPrinter, m.Expr.Visitor[None], m.Stmt.Visitor[None]):
|
||||||
def visit_type_stmt(self, stmt: m.TypeStmt):
|
#Statements
|
||||||
self._write_line("TypeStmt")
|
|
||||||
|
def visit_simple_type_stmt(self, stmt: m.SimpleTypeStmt):
|
||||||
|
self._write_line("SimpleTypeStmt")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line(f'name: "{stmt.name.lexeme}"')
|
self._write_line(f'name: "{stmt.name.lexeme}"')
|
||||||
self._write_line("bases")
|
self._write_optional_child("template", stmt.template)
|
||||||
|
self._write_line("base")
|
||||||
|
with self._child_level(single=True):
|
||||||
|
stmt.base.accept(self)
|
||||||
|
self._write_optional_child("constraint", stmt.constraint, last=True)
|
||||||
|
|
||||||
|
def visit_complex_type_stmt(self, stmt: m.ComplexTypeStmt):
|
||||||
|
self._write_line("ComplexTypeStmt")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line(f'name: "{stmt.name.lexeme}"')
|
||||||
|
self._write_optional_child("template", stmt.template)
|
||||||
|
self._write_line("properties", last=True)
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
for i, base in enumerate(stmt.bases):
|
for i, prop in enumerate(stmt.properties):
|
||||||
self._idx = i
|
self._idx = i
|
||||||
if i == len(stmt.bases) - 1:
|
if i == len(stmt.properties) - 1:
|
||||||
self._mark_last()
|
self._mark_last()
|
||||||
base.accept(self)
|
prop.accept(self)
|
||||||
self._write_optional_child("body", stmt.body, last=True)
|
|
||||||
|
|
||||||
def visit_property_stmt(self, stmt: m.PropertyStmt):
|
def visit_property_stmt(self, stmt: m.PropertyStmt):
|
||||||
self._write_line("PropertyStmt")
|
self._write_line("PropertyStmt")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line(f'name: "{stmt.name.lexeme}"')
|
self._write_line(f'name: "{stmt.name.lexeme}"')
|
||||||
self._write_line("type", last=True)
|
self._write_line("type")
|
||||||
with self._child_level():
|
with self._child_level(single=True):
|
||||||
self._mark_last()
|
|
||||||
stmt.type.accept(self)
|
stmt.type.accept(self)
|
||||||
|
self._write_optional_child("constraint", stmt.constraint, last=True)
|
||||||
|
|
||||||
|
def visit_extend_stmt(self, stmt: m.ExtendStmt) -> None:
|
||||||
|
self._write_line("ExtendStmt")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line("type")
|
||||||
|
with self._child_level(single=True):
|
||||||
|
stmt.type.accept(self)
|
||||||
|
self._write_line("operations", last=True)
|
||||||
|
with self._child_level():
|
||||||
|
for i, op in enumerate(stmt.operations):
|
||||||
|
self._idx = i
|
||||||
|
if i == len(stmt.operations) - 1:
|
||||||
|
self._mark_last()
|
||||||
|
op.accept(self)
|
||||||
|
|
||||||
def visit_op_stmt(self, stmt: m.OpStmt) -> None:
|
def visit_op_stmt(self, stmt: m.OpStmt) -> None:
|
||||||
self._write_line("OpStmt")
|
self._write_line("OpStmt")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line("left")
|
self._write_line(f'name: "{stmt.name.lexeme}"')
|
||||||
with self._child_level():
|
|
||||||
self._mark_last()
|
|
||||||
stmt.left.accept(self)
|
|
||||||
|
|
||||||
self._write_line(f'op: "{stmt.op.lexeme}"')
|
self._write_line("operand")
|
||||||
|
with self._child_level(single=True):
|
||||||
self._write_line("right")
|
stmt.operand.accept(self)
|
||||||
with self._child_level():
|
|
||||||
self._mark_last()
|
|
||||||
stmt.right.accept(self)
|
|
||||||
|
|
||||||
self._write_line("result", last=True)
|
self._write_line("result", last=True)
|
||||||
with self._child_level():
|
with self._child_level(single=True):
|
||||||
self._mark_last()
|
|
||||||
stmt.result.accept(self)
|
stmt.result.accept(self)
|
||||||
|
|
||||||
def visit_constraint_stmt(self, stmt: m.ConstraintStmt):
|
def visit_predicate_stmt(self, stmt: m.PredicateStmt):
|
||||||
self._write_line("ConstraintStmt")
|
self._write_line("PredicateStmt")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line(f'name: "{stmt.name.lexeme}"')
|
self._write_line(f'name: "{stmt.name.lexeme}"')
|
||||||
self._write_line("constraint", last=True)
|
self._write_line(f'subject: "{stmt.subject.lexeme}"')
|
||||||
with self._child_level():
|
self._write_line("type")
|
||||||
self._mark_last()
|
with self._child_level(single=True):
|
||||||
stmt.constraint.accept(self)
|
stmt.type.accept(self)
|
||||||
|
self._write_line("condition", last=True)
|
||||||
|
with self._child_level(single=True):
|
||||||
|
stmt.condition.accept(self)
|
||||||
|
|
||||||
def visit_type_expr(self, expr: m.TypeExpr):
|
# Expressions
|
||||||
self._write_line("TypeExpr")
|
|
||||||
|
def visit_simple_type_expr(self, expr: m.SimpleTypeExpr):
|
||||||
|
self._write_line("SimpleTypeExpr")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line(f'name: "{expr.name.lexeme}"')
|
self._write_line(f'name: "{expr.name.lexeme}"')
|
||||||
self._write_line("constraints", last=True)
|
self._write_line(f"optional: {expr.optional}", last=True)
|
||||||
with self._child_level():
|
|
||||||
for i, constraint in enumerate(expr.constraints):
|
|
||||||
self._idx = i
|
|
||||||
if i == len(expr.constraints) - 1:
|
|
||||||
self._mark_last()
|
|
||||||
constraint.accept(self)
|
|
||||||
|
|
||||||
def visit_constraint_expr(self, expr: m.ConstraintExpr):
|
def visit_logical_expr(self, expr: m.LogicalExpr):
|
||||||
self._write_line("ConstraintExpr")
|
self._write_line("LogicalExpr")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line("left")
|
self._write_line("left")
|
||||||
with self._child_level():
|
with self._child_level(single=True):
|
||||||
self._mark_last()
|
|
||||||
expr.left.accept(self)
|
expr.left.accept(self)
|
||||||
|
|
||||||
self._write_line(f"operator: {expr.op.lexeme}")
|
self._write_line(f"operator: {expr.operator.lexeme}")
|
||||||
|
|
||||||
self._write_line("right", last=True)
|
self._write_line("right", last=True)
|
||||||
with self._child_level():
|
with self._child_level(single=True):
|
||||||
self._mark_last()
|
|
||||||
expr.right.accept(self)
|
expr.right.accept(self)
|
||||||
|
|
||||||
def visit_type_body_expr(self, expr: m.TypeBodyExpr):
|
def visit_binary_expr(self, expr: m.BinaryExpr):
|
||||||
self._write_line("TypeBodyExpr")
|
self._write_line("BinaryExpr")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line("properties", last=True)
|
self._write_line("left")
|
||||||
with self._child_level():
|
with self._child_level(single=True):
|
||||||
for i, property in enumerate(expr.properties):
|
expr.left.accept(self)
|
||||||
self._idx = i
|
|
||||||
if i == len(expr.properties) - 1:
|
|
||||||
self._mark_last()
|
|
||||||
property.accept(self)
|
|
||||||
|
|
||||||
def visit_wildcard_expr(self, expr: m.WildcardExpr) -> None:
|
self._write_line(f"operator: {expr.operator.lexeme}")
|
||||||
self._write_line("WildcardExpr")
|
|
||||||
|
self._write_line("right", last=True)
|
||||||
|
with self._child_level(single=True):
|
||||||
|
expr.right.accept(self)
|
||||||
|
|
||||||
|
def visit_unary_expr(self, expr: m.UnaryExpr):
|
||||||
|
self._write_line("UnaryExpr")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line(f"operator: {expr.operator.lexeme}")
|
||||||
|
|
||||||
|
self._write_line("right", last=True)
|
||||||
|
with self._child_level(single=True):
|
||||||
|
expr.right.accept(self)
|
||||||
|
|
||||||
|
def visit_get_expr(self, expr: m.GetExpr):
|
||||||
|
self._write_line("GetExpr")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line("expr")
|
||||||
|
with self._child_level(single=True):
|
||||||
|
expr.expr.accept(self)
|
||||||
|
self._write_line(f'name: "{expr.name.lexeme}"', last=True)
|
||||||
|
|
||||||
|
def visit_variable_expr(self, expr: m.VariableExpr):
|
||||||
|
self._write_line("VariableExpr")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line(f'name: "{expr.name.lexeme}"', last=True)
|
||||||
|
|
||||||
|
def visit_grouping_expr(self, expr: m.GroupingExpr):
|
||||||
|
self._write_line("GroupingExpr")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line("expr", last=True)
|
||||||
|
with self._child_level(single=True):
|
||||||
|
expr.expr.accept(self)
|
||||||
|
|
||||||
def visit_literal_expr(self, expr: m.LiteralExpr) -> None:
|
def visit_literal_expr(self, expr: m.LiteralExpr) -> None:
|
||||||
self._write_line("LiteralExpr")
|
self._write_line("LiteralExpr")
|
||||||
with self._child_level():
|
with self._child_level():
|
||||||
self._write_line(f"value: {expr.value}", last=True)
|
self._write_line(f"value: {expr.value}", last=True)
|
||||||
|
|
||||||
|
def visit_wildcard_expr(self, expr: m.WildcardExpr) -> None:
|
||||||
|
self._write_line("WildcardExpr")
|
||||||
|
|
||||||
|
def visit_template_expr(self, expr: m.TemplateExpr) -> None:
|
||||||
|
self._write_line("TemplateExpr")
|
||||||
|
with self._child_level(single=True):
|
||||||
|
self._write_line("type")
|
||||||
|
with self._child_level(single=True):
|
||||||
|
expr.type.accept(self)
|
||||||
|
|
||||||
|
def visit_type_expr(self, expr: m.TypeExpr):
|
||||||
|
self._write_line("TypeExpr")
|
||||||
|
with self._child_level():
|
||||||
|
self._write_line(f'name: "{expr.name.lexeme}"')
|
||||||
|
self._write_optional_child("template", expr.template)
|
||||||
|
self._write_line(f"optional: {expr.optional}", last=True)
|
||||||
|
|
||||||
|
|
||||||
class MidasPrinter(m.Expr.Visitor[str], m.Stmt.Visitor[str]):
|
class MidasPrinter(m.Expr.Visitor[str], m.Stmt.Visitor[str]):
|
||||||
def __init__(self, indent: int = 4):
|
def __init__(self, indent: int = 4):
|
||||||
|
|||||||
29
test.py
29
test.py
@@ -1,40 +1,21 @@
|
|||||||
import importlib
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from core.ast.printer import AnnotationAstPrinter, MidasAstPrinter
|
from core.ast.printer import MidasAstPrinter
|
||||||
from lexer.annotations import AnnotationLexer
|
|
||||||
from lexer.midas import MidasLexer
|
from lexer.midas import MidasLexer
|
||||||
from lexer.token import Token
|
from lexer.token import Token
|
||||||
from parser.annotations import AnnotationParser
|
|
||||||
from parser.midas import MidasParser
|
from parser.midas import MidasParser
|
||||||
|
|
||||||
|
|
||||||
def test_annotation():
|
|
||||||
# Frame annotation
|
|
||||||
mod = importlib.import_module("examples.00_syntax_prototype.01_simple_types")
|
|
||||||
|
|
||||||
annotation: str = mod.__annotations__["df"]
|
|
||||||
lexer: AnnotationLexer = AnnotationLexer(annotation, "01_simple_types.py")
|
|
||||||
tokens: list[Token] = lexer.process()
|
|
||||||
# print([f"{t.type.name}('{t.lexeme}')" for t in tokens])
|
|
||||||
|
|
||||||
parser = AnnotationParser(tokens)
|
|
||||||
parsed = parser.parse()
|
|
||||||
print(parsed)
|
|
||||||
for err in parser.errors:
|
|
||||||
print(err.get_report())
|
|
||||||
printer = AnnotationAstPrinter()
|
|
||||||
if parsed is not None:
|
|
||||||
print(printer.print(parsed))
|
|
||||||
|
|
||||||
|
|
||||||
def test_midas():
|
def test_midas():
|
||||||
# Midas type definitions
|
# Midas type definitions
|
||||||
path: Path = Path("examples") / "00_syntax_prototype" / "02_custom_types.midas"
|
path: Path = Path("examples") / "00_syntax_prototype" / "03_custom_types_v2.midas"
|
||||||
definitions: str = path.read_text()
|
definitions: str = path.read_text()
|
||||||
midas_lexer: MidasLexer = MidasLexer(definitions, path.name)
|
midas_lexer: MidasLexer = MidasLexer(definitions, path.name)
|
||||||
tokens: list[Token] = midas_lexer.process()
|
tokens: list[Token] = midas_lexer.process()
|
||||||
# print([f"{t.type.name}('{t.lexeme}')" for t in tokens])
|
# print([f"{t.type.name}('{t.lexeme}')" for t in tokens])
|
||||||
|
with open("tokens.json", "w") as f:
|
||||||
|
json.dump([f"{t.type.name}('{t.lexeme}')" for t in tokens], f, indent=4)
|
||||||
|
|
||||||
parser = MidasParser(tokens)
|
parser = MidasParser(tokens)
|
||||||
parsed = parser.parse()
|
parsed = parser.parse()
|
||||||
|
|||||||
Reference in New Issue
Block a user