From aec6b7aa7be54d304726ed034afcad07b47cb912 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Sun, 14 Jun 2026 16:53:38 +0200 Subject: [PATCH] feat(parser): add slice expression --- gen/python.py | 6 ++++++ midas/ast/printer.py | 7 +++++++ midas/ast/python.py | 13 +++++++++++++ midas/cli/highlighter.py | 8 ++++++++ midas/parser/python.py | 9 +++++++++ tests/serializer/python.py | 9 +++++++++ 6 files changed, 52 insertions(+) diff --git a/gen/python.py b/gen/python.py index b7c38ec..35908f7 100644 --- a/gen/python.py +++ b/gen/python.py @@ -148,4 +148,10 @@ class SubscriptExpr: index: Expr +class SliceExpr: + lower: Optional[Expr] + upper: Optional[Expr] + step: Optional[Expr] + + ###< diff --git a/midas/ast/printer.py b/midas/ast/printer.py index 3495883..e52472c 100644 --- a/midas/ast/printer.py +++ b/midas/ast/printer.py @@ -729,3 +729,10 @@ class PythonAstPrinter( self._write_line("index", last=True) with self._child_level(single=True): expr.index.accept(self) + + def visit_slice_expr(self, expr: p.SliceExpr) -> None: + self._write_line("SliceExpr") + with self._child_level(): + self._write_optional_child("lower", expr.lower) + self._write_optional_child("upper", expr.upper) + self._write_optional_child("step", expr.step, last=True) diff --git a/midas/ast/python.py b/midas/ast/python.py index a199b89..f025e2f 100644 --- a/midas/ast/python.py +++ b/midas/ast/python.py @@ -227,6 +227,9 @@ class Expr(ABC): @abstractmethod def visit_subscript_expr(self, expr: SubscriptExpr) -> T: ... + @abstractmethod + def visit_slice_expr(self, expr: SliceExpr) -> T: ... + @dataclass(frozen=True) class BinaryExpr(Expr): @@ -336,3 +339,13 @@ class SubscriptExpr(Expr): def accept(self, visitor: Expr.Visitor[T]) -> T: return visitor.visit_subscript_expr(self) + + +@dataclass(frozen=True) +class SliceExpr(Expr): + lower: Optional[Expr] + upper: Optional[Expr] + step: Optional[Expr] + + def accept(self, visitor: Expr.Visitor[T]) -> T: + return visitor.visit_slice_expr(self) diff --git a/midas/cli/highlighter.py b/midas/cli/highlighter.py index 3c3f07e..bc7727c 100644 --- a/midas/cli/highlighter.py +++ b/midas/cli/highlighter.py @@ -222,6 +222,14 @@ class PythonHighlighter( expr.object.accept(self) expr.index.accept(self) + def visit_slice_expr(self, expr: p.SliceExpr) -> None: + if expr.lower is not None: + expr.lower.accept(self) + if expr.upper is not None: + expr.upper.accept(self) + if expr.step is not None: + expr.step.accept(self) + class MidasHighlighter( Highlighter, m.Stmt.Visitor[None], m.Expr.Visitor[None], m.Type.Visitor[None] diff --git a/midas/parser/python.py b/midas/parser/python.py index 8c1f5a7..a0726da 100644 --- a/midas/parser/python.py +++ b/midas/parser/python.py @@ -22,6 +22,7 @@ from midas.ast.python import ( LogicalExpr, MidasType, ReturnStmt, + SliceExpr, Stmt, SubscriptExpr, TernaryExpr, @@ -431,6 +432,14 @@ class PythonParser: index=self.parse_expr(index), ) + case ast.Slice(lower=lower, upper=upper, step=step): + return SliceExpr( + location=location, + lower=self.parse_expr(lower) if lower is not None else None, + upper=self.parse_expr(upper) if upper is not None else None, + step=self.parse_expr(step) if step is not None else None, + ) + case _: raise UnsupportedSyntaxError(node) diff --git a/tests/serializer/python.py b/tests/serializer/python.py index 73b8b84..b090eea 100644 --- a/tests/serializer/python.py +++ b/tests/serializer/python.py @@ -21,6 +21,7 @@ from midas.ast.python import ( LogicalExpr, MidasType, ReturnStmt, + SliceExpr, Stmt, SubscriptExpr, TernaryExpr, @@ -260,3 +261,11 @@ class PythonAstJsonSerializer( "object": expr.object.accept(self), "index": expr.index.accept(self), } + + def visit_slice_expr(self, expr: SliceExpr) -> dict: + return { + "_type": "SliceExpr", + "lower": self._serialize_optional(expr.lower), + "upper": self._serialize_optional(expr.upper), + "step": self._serialize_optional(expr.step), + }