From 539084f6d8007d683ae51b4e90b6e9a71fd58427 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Mon, 18 May 2026 09:17:57 +0200 Subject: [PATCH] feat(parser): add documentation to Midas parser --- parser/midas.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/parser/midas.py b/parser/midas.py index c056038..bf7c1d7 100644 --- a/parser/midas.py +++ b/parser/midas.py @@ -16,6 +16,8 @@ from parser.errors import ParsingError class MidasParser(Parser): + """A simple parser for midas type definitions""" + SYNC_BOUNDARY: set[TokenType] = {TokenType.TYPE, TokenType.OP, TokenType.CONSTRAINT} def parse(self) -> list[Stmt]: @@ -29,6 +31,11 @@ class MidasParser(Parser): return statements def synchronize(self): + """Skip tokens until a synchronization boundary is found + + This method allows gracefully recovering from a parse error + to a safe place and continue parsing + """ self.advance() while not self.is_at_end(): if self.previous().type == TokenType.NEWLINE: @@ -38,6 +45,13 @@ class MidasParser(Parser): self.advance() def declaration(self) -> Optional[Stmt]: + """Try and parse a declaration + + Any parsing error is caught and None is returned + + Returns: + Optional[Stmt]: the parsed Midas statement, or None if a ParsingError was raised + """ try: if self.match(TokenType.TYPE): return self.type_declaration() @@ -50,6 +64,13 @@ class MidasParser(Parser): return None def type_declaration(self) -> TypeStmt: + """Parse a type declaration + + A type declaration is written `type Name` optionally followed by a brace-wrapped body + + Returns: + TypeStmt: the parsed type declaration statement + """ name: Token = self.consume(TokenType.IDENTIFIER, "Expected type name") self.consume(TokenType.LESS, "Expected '<' after type name") bases: list[TypeExpr] = [] @@ -66,6 +87,11 @@ class MidasParser(Parser): return TypeStmt(name=name, bases=bases, body=body) def type_expr(self) -> TypeExpr: + """Parse a type expression + + Returns: + TypeExpr: the parsed type expression + """ name: Token = self.consume(TokenType.IDENTIFIER, "Expected type name") constraints: list[ConstraintExpr] = [] @@ -75,10 +101,23 @@ class MidasParser(Parser): return TypeExpr(name=name, constraints=constraints) def constraint_expr(self) -> ConstraintExpr: + """Parse a type constraint + + Returns: + ConstraintExpr: the parsed type constraint expression + """ # TODO return ConstraintExpr() def type_body_expr(self) -> TypeBodyExpr: + """Parse a type definition body + + A type definition body is a set of whitespace-separated + property statements enclosed in curly braces + + Returns: + TypeBodyExpr: the parsed type body expression + """ 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(): @@ -87,12 +126,26 @@ class MidasParser(Parser): return TypeBodyExpr(properties=properties) def property_stmt(self) -> PropertyStmt: + """Parse a property statement + + A type property statement is written `name: Type` + + Returns: + PropertyStmt: the parsed property statement + """ 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) def op_declaration(self) -> OpStmt: + """Parse an operation definition + + An operation is written `op operator = ` where `operator` can be any single token + + Returns: + OpStmt: the parsed operation statement + """ self.consume(TokenType.LESS, "Expected '<' before first type") left: TypeExpr = self.type_expr() self.consume(TokenType.GREATER, "Expected '>' after first type") @@ -112,6 +165,13 @@ class MidasParser(Parser): return OpStmt(left=left, op=op, right=right, result=result) def constraint_declaration(self) -> ConstraintStmt: + """Parse a type constraint declaration + + A constraint is written `constraint Name = constraint_expression` + + Returns: + ConstraintStmt: the parsed constraint declaration statement + """ name: Token = self.consume(TokenType.IDENTIFIER, "Expected constraint name") self.consume(TokenType.EQUAL, "Expected '=' after constraint name") constraint: ConstraintExpr = self.constraint_expr()