def Choice(*expressions: _Def): exprs = list(map(_validate, expressions)) if len(exprs) == 1: return exprs[0] else: _exprs: List[Definition] = [] for expr in exprs: if expr.op == CHC: _exprs.extend(expr.args[0]) else: _exprs.append(expr) return Definition(CHC, (_exprs, ))
def Class(arg, negate: bool = False): ranges: List[Tuple[str, Union[str, None]]] if isinstance(arg, list): ranges = arg else: assert isinstance(arg, str) ranges = [] i = 0 while i < len(arg) - 2: if arg[i + 1] == '-': ranges.append((arg[i], arg[i + 2])) i += 3 else: ranges.append((arg[i], None)) i += 1 while i < len(arg): ranges.append((arg[i], None)) i += 1 return Definition(CLS, (ranges, negate))
def Regex(pattern: Union[str, Pattern], flags: int = 0): return Definition(RGX, (pattern, flags))
def Literal(string: str): return Definition(LIT, (string, ))
def Debug(expression: _Def): return Definition(DBG, (_validate(expression), ))
def Dot(): return Definition(DOT, ())
def Bind(expression: _Def, name: str): assert isinstance(name, str) return Definition(BND, (_validate(expression), name))
def Rule(expression: _Def, action: Callable, name: str = ANONYMOUS): if action and not isinstance(action, Action): action = Call(action) return Definition(RUL, (_validate(expression), action, name))
def Not(expression: _Def): return Definition(NOT, (_validate(expression), ))
def Capture(expression: _Def): return Definition(CAP, (_validate(expression), ))
def And(expression: _Def): return Definition(AND, (_validate(expression), ))
def Nonterminal(name: str): return Definition(SYM, (name, ))
def Plus(expression: _Def): expression = _validate(expression) if expression.op in (OPT, STR, PLS): raise GrammarError('multiple repeat operators') return Definition(PLS, (expression, ))
def _debug_combining(defn: Definition, defs): inner = [_debug(sub, defs) for sub in defn.args[0]] dbg_defn = Definition(defn.op, (inner, ) + defn.args[1:]) return Debug(dbg_defn)
def _debug_recursive(defn: Definition, defs): inner = _debug(defn.args[0], defs) dbg_defn = Definition(defn.op, (inner, ) + defn.args[1:]) return Debug(dbg_defn)