"""Expression utilities — all functions return grammar.py AST nodes.""" from .grammar import Symbol, Concat, Alt, Plus, Optional, Star, Epsilon, Empty def sym(s): """Create a symbol node.""" return Symbol(s) def concat(*parts): """Create concatenation AST node.""" parts = [p for p in parts if p and not isinstance(p, Epsilon)] if not parts: return Epsilon() if len(parts) == 1: return parts[0] return Concat(parts) def disj(*parts): """Create disjunction AST node.""" parts = [p for p in parts if p and not isinstance(p, Empty)] if not parts: return Empty() if len(parts) == 1: return parts[0] return Alt(parts) def star(expr): """Create one-or-more repetition AST node (r+).""" if not expr or isinstance(expr, Empty): return expr or Empty() if isinstance(expr, Epsilon): return Epsilon() return Plus(expr) def optional(expr): """Create optional AST node (r?).""" if not expr or isinstance(expr, Empty): return Epsilon() if isinstance(expr, Epsilon): return Epsilon() return Optional(expr) def alphabet(node): """Return set of alphabet symbols in AST node.""" from .grammar import alphabet as _grammar_alphabet return _grammar_alphabet(node)