def recurse(p: Parser) -> Union[DiagramItem, str, None]: # Transform parsers are just ignored if isinstance(p, _Transform): return recurse(p.children[0]) elif isinstance(p, Opt): # Opt parsers are straightforwardly wrapped into an Optional return Optional(recurse(p.parser)) elif isinstance(p, _Extract): # Extract is ignored return recurse(p.parser) # For list parsers, we create a sequence with the right separator # and sub-parser. elif isinstance(p, List): sep = recurse(p.sep) if p.sep else None child = recurse(p.parser) if p.empty_valid: return ZeroOrMore(child, repeat=sep) else: return OneOrMore(child, repeat=sep) # For defers, we just return the rule name elif isinstance(p, Defer): return p.rule_name # For tokens, we return either the quoted original string, or the DSL # name. elif isinstance(p, _Token): if p._original_string: return repr(p._original_string) else: return p.val.dsl_name children = [] for c in p.children: res = recurse(c) if res is not None: children.append(res) if isinstance(p, Or): if len(children) == 0: return None children = sorted(children, key=lambda c: isinstance(c, Skip)) return Choice(0, *children) elif isinstance(p, _Row): if len(children) == 0: return Skip() return Sequence(*children) else: return None
def expr(self, children): if len(children) == 3: base, mi, ma = children if int(mi.value) == 0: if int(ma.value) == 1: return Optional(base) return ZeroOrMore(base, Comment(f'{mi.value}..{ma.value}')) else: return OneOrMore(base, Comment(f'{mi.value}..{ma.value}')) base, op = children if op.type != 'OP': return OneOrMore(base, Comment(f'{op.value} times')) if op.value == '+': return OneOrMore(base) elif op.value == '*': return ZeroOrMore(base) elif op.value == '?': return Optional(base) else: raise ValueError(f"Unsupported Operator {op!r}")
import sys from railroad import Diagram, Choice, OneOrMore d = Diagram("A", Choice(0, "B", "C"), OneOrMore("D")) with open('diagram.html', 'w') as f: d.writeSvg(f.write)
def token(): return OneOrMore(Choice(0, alphanum(), tspecials()))
def isdn_subaddress(): return Sequence(";isub=", OneOrMore(NonTerminal("uric")))
def pvalue(): return OneOrMore(NonTerminal("paramchar"))
def pname(): return OneOrMore(Choice(0, alphanum(), "-"))
def extension(): return Sequence(";ext=", OneOrMore(NonTerminal("phonedigit")))
def segment_nz(): return OneOrMore(Choice(0, *pchar()))
def ipvfuture(): return [ "v", OneOrMore(NonTerminal("HEXDIG")), ".", OneOrMore(Choice(0, unreserved(), sub_delims(), ":")) ]