From 3b40abaa2b4bee9c6d2ad51deca55a009d280f7e Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Thu, 14 May 2026 02:29:08 +0200 Subject: [PATCH] feat(parser): parse type body --- core/ast/printer.py | 11 +++++++---- parser/midas.py | 26 +++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/core/ast/printer.py b/core/ast/printer.py index 8c873eb..46c45da 100644 --- a/core/ast/printer.py +++ b/core/ast/printer.py @@ -50,7 +50,9 @@ class AstPrinter(Generic[T]): if self._levels: self._levels[-1] = _Level.LAST - def _write_line(self, text: str): + def _write_line(self, text: str, *, last: bool = False): + if last: + self._mark_last() indent: str = self._build_indent() if self._idx is not None: text = f"[{self._idx}] {text}" @@ -152,15 +154,16 @@ class MidasAstPrinter(AstPrinter, m.Expr.Visitor[None], m.Stmt.Visitor[None]): self._write_line("PropertyStmt") with self._child_level(): self._write_line(f'name: "{stmt.name.lexeme}"') - self._write_line("type") + self._write_line("type", last=True) with self._child_level(): + self._mark_last() stmt.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_line("constraints") + self._write_line("constraints", last=True) with self._child_level(): for i, constraint in enumerate(expr.constraints): self._idx = i @@ -174,7 +177,7 @@ class MidasAstPrinter(AstPrinter, m.Expr.Visitor[None], m.Stmt.Visitor[None]): def visit_type_body_expr(self, expr: m.TypeBodyExpr): self._write_line("TypeBodyExpr") with self._child_level(): - self._write_line("properties") + self._write_line("properties", last=True) with self._child_level(): for i, property in enumerate(expr.properties): self._idx = i diff --git a/parser/midas.py b/parser/midas.py index fd02c04..f03029d 100644 --- a/parser/midas.py +++ b/parser/midas.py @@ -1,6 +1,13 @@ from typing import Optional -from core.ast.midas import ConstraintExpr, Stmt, TypeBodyExpr, TypeExpr, TypeStmt +from core.ast.midas import ( + ConstraintExpr, + PropertyStmt, + Stmt, + TypeBodyExpr, + TypeExpr, + TypeStmt, +) from lexer.token import Token, TokenType from parser.base import Parser from parser.errors import ParsingError @@ -51,6 +58,9 @@ class MidasParser(Parser): self.consume(TokenType.GREATER, "Expected '>' after base type") body: Optional[TypeBodyExpr] = None + + if self.check(TokenType.LEFT_BRACE): + body = self.type_body_expr() return TypeStmt(name=name, bases=bases, body=body) def type_expr(self) -> TypeExpr: @@ -65,3 +75,17 @@ class MidasParser(Parser): def constraint_expr(self) -> ConstraintExpr: # TODO return ConstraintExpr() + + def type_body_expr(self) -> TypeBodyExpr: + self.consume(TokenType.LEFT_BRACE, "Expected '{' to start type body") + properties: list[PropertyStmt] = [] + while not self.check(TokenType.RIGHT_BRACE) and not self.is_at_end(): + properties.append(self.property_stmt()) + self.consume(TokenType.RIGHT_BRACE, "Unclosed type body") + return TypeBodyExpr(properties=properties) + + def property_stmt(self) -> PropertyStmt: + name: Token = self.consume(TokenType.IDENTIFIER, "Expected property name") + self.consume(TokenType.COLON, "Expected ':' after property name") + type: TypeExpr = self.type_expr() + return PropertyStmt(name=name, type=type)