From 0af31a6f859574e98e3ce771d94d56fd0714154e Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Thu, 14 May 2026 02:37:50 +0200 Subject: [PATCH] feat(parser): parse op statements --- core/ast/midas.py | 14 ++++++++++++++ core/ast/printer.py | 20 ++++++++++++++++++++ parser/midas.py | 24 ++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/core/ast/midas.py b/core/ast/midas.py index 1c85f66..6f64b57 100644 --- a/core/ast/midas.py +++ b/core/ast/midas.py @@ -24,6 +24,9 @@ class Stmt(ABC): @abstractmethod def visit_property_stmt(self, stmt: PropertyStmt) -> T: ... + @abstractmethod + def visit_op_stmt(self, stmt: OpStmt) -> T: ... + @dataclass(frozen=True) class TypeStmt(Stmt): @@ -44,6 +47,17 @@ class PropertyStmt(Stmt): return visitor.visit_property_stmt(self) +@dataclass(frozen=True) +class OpStmt(Stmt): + left: TypeExpr + op: Token + right: TypeExpr + result: TypeExpr + + def accept(self, visitor: Stmt.Visitor[T]) -> T: + return visitor.visit_op_stmt(self) + + # Expressions diff --git a/core/ast/printer.py b/core/ast/printer.py index 46c45da..c745221 100644 --- a/core/ast/printer.py +++ b/core/ast/printer.py @@ -159,6 +159,26 @@ class MidasAstPrinter(AstPrinter, m.Expr.Visitor[None], m.Stmt.Visitor[None]): self._mark_last() stmt.type.accept(self) + def visit_op_stmt(self, stmt: m.OpStmt) -> None: + self._write_line("OpStmt") + with self._child_level(): + self._write_line("left") + with self._child_level(): + self._mark_last() + stmt.left.accept(self) + + self._write_line(f'op: "{stmt.op.lexeme}"') + + self._write_line("right") + with self._child_level(): + self._mark_last() + stmt.right.accept(self) + + self._write_line("result", last=True) + with self._child_level(): + self._mark_last() + stmt.result.accept(self) + def visit_type_expr(self, expr: m.TypeExpr): self._write_line("TypeExpr") with self._child_level(): diff --git a/parser/midas.py b/parser/midas.py index f03029d..bcf1477 100644 --- a/parser/midas.py +++ b/parser/midas.py @@ -2,6 +2,7 @@ from typing import Optional from core.ast.midas import ( ConstraintExpr, + OpStmt, PropertyStmt, Stmt, TypeBodyExpr, @@ -39,8 +40,8 @@ class MidasParser(Parser): try: if self.match(TokenType.TYPE): return self.type_declaration() - # if self.match(TokenType.OP): - # return self.op_declaration() + if self.match(TokenType.OP): + return self.op_declaration() # if self.match(TokenType.CONSTRAINT): # return self.constraint_declaration() except ParsingError: @@ -89,3 +90,22 @@ class MidasParser(Parser): self.consume(TokenType.COLON, "Expected ':' after property name") type: TypeExpr = self.type_expr() return PropertyStmt(name=name, type=type) + + def op_declaration(self) -> OpStmt: + self.consume(TokenType.LESS, "Expected '<' before first type") + left: TypeExpr = self.type_expr() + self.consume(TokenType.GREATER, "Expected '>' after first type") + + op: Token = self.advance() + + self.consume(TokenType.LESS, "Expected '<' before second type") + right: TypeExpr = self.type_expr() + self.consume(TokenType.GREATER, "Expected '>' after second type") + + self.consume(TokenType.EQUAL, "Expected '=' after second type") + + self.consume(TokenType.LESS, "Expected '<' before result type") + result: TypeExpr = self.type_expr() + self.consume(TokenType.GREATER, "Expected '>' after result type") + + return OpStmt(left=left, op=op, right=right, result=result)