def parser_from_source(src, converters=None): grammar = expand_macros(parse_grammar(src)) invalid = get_invalid(check_grammar(grammar)) if invalid: raise ValueError("Following rules are invalid: {}".format( ", ".join(invalid))) types = infer_types(grammar) if types is None: raise ValueError("Got invalid type") ast = gen_ast_module(types) return compile_parser(grammar, ast, converters)
def generate(): grammar = expand_macros(parse_grammar(source)) types = infer_types(grammar) new_parser = compile_parser(grammar, gen_ast_module(types), converters) grammar = expand_macros(new_parser.parse(source)) types = infer_types(grammar) with open("descent/ast.py", "w") as fp: fp.write(gen_ast_module_src(types)) with open("descent/grammar.py", "w") as fp: fp.write("from collections import OrderedDict\n\n") fp.write( "from .ast import " + ", ".join(type_.name for type_ in types) + "\n\n\n" ) fp.write("grammar = OrderedDict([\n") for name, expr in grammar.items(): fp.write(" ({!r}, {!r}),\n".format(name, expr)) fp.write("])\n")
def generate(input): parsed = parse_grammar(input) if parsed is None: raise ValueError("Invald grammar") grammar = expand_macros(parsed) invalid = get_invalid(check_grammar(grammar)) if invalid: raise ValueError("Invalid rules: {}".format(", ".join(invalid))) types = infer_types(grammar) yield "from collections import OrderedDict\n" yield "from descent.ast import *" yield "from descent.combinators import compile_parser\n\n" yield gen_ast_module_src(types) yield "" yield "" yield "parsed_grammar = OrderedDict([" for name, body in grammar.items(): yield " ({!r}, {!r}),".format(name, body) yield "])\n\n" yield "parser = compile_parser(parsed_grammar, types_map)"
def test_parse(input, result): assert check_grammar(expand_macros(parse_grammar(input))) == result
def test_parse(input, result): types = infer_types(expand_macros(parse_grammar(input))) assert types is None and result is None or set(types) == result