|
11 | 11 | import token
|
12 | 12 | import traceback
|
13 | 13 |
|
| 14 | +from typing import Tuple |
| 15 | + |
| 16 | +from pegen.build import Grammar, Parser, Tokenizer, ParserGenerator |
| 17 | + |
| 18 | + |
| 19 | +def generate_c_code( |
| 20 | + args: argparse.Namespace, |
| 21 | +) -> Tuple[Grammar, Parser, Tokenizer, ParserGenerator]: |
| 22 | + from pegen.build import build_c_parser_and_generator |
| 23 | + |
| 24 | + verbose = args.verbose |
| 25 | + verbose_tokenizer = verbose >= 3 |
| 26 | + verbose_parser = verbose == 2 or verbose >= 4 |
| 27 | + try: |
| 28 | + grammar, parser, tokenizer, gen = build_c_parser_and_generator( |
| 29 | + args.grammar_filename, |
| 30 | + args.tokens_filename, |
| 31 | + args.output, |
| 32 | + args.compile_extension, |
| 33 | + verbose_tokenizer, |
| 34 | + verbose_parser, |
| 35 | + args.verbose, |
| 36 | + keep_asserts_in_extension=False if args.optimized else True, |
| 37 | + skip_actions=args.skip_actions, |
| 38 | + ) |
| 39 | + return grammar, parser, tokenizer, gen |
| 40 | + except Exception as err: |
| 41 | + if args.verbose: |
| 42 | + raise # Show traceback |
| 43 | + traceback.print_exception(err.__class__, err, None) |
| 44 | + sys.stderr.write("For full traceback, use -v\n") |
| 45 | + sys.exit(1) |
| 46 | + |
| 47 | + |
| 48 | +def generate_python_code( |
| 49 | + args: argparse.Namespace, |
| 50 | +) -> Tuple[Grammar, Parser, Tokenizer, ParserGenerator]: |
| 51 | + from pegen.build import build_python_parser_and_generator |
| 52 | + |
| 53 | + verbose = args.verbose |
| 54 | + verbose_tokenizer = verbose >= 3 |
| 55 | + verbose_parser = verbose == 2 or verbose >= 4 |
| 56 | + try: |
| 57 | + grammar, parser, tokenizer, gen = build_python_parser_and_generator( |
| 58 | + args.grammar_filename, |
| 59 | + args.output, |
| 60 | + verbose_tokenizer, |
| 61 | + verbose_parser, |
| 62 | + skip_actions=args.skip_actions, |
| 63 | + ) |
| 64 | + return grammar, parser, tokenizer, gen |
| 65 | + except Exception as err: |
| 66 | + if args.verbose: |
| 67 | + raise # Show traceback |
| 68 | + traceback.print_exception(err.__class__, err, None) |
| 69 | + sys.stderr.write("For full traceback, use -v\n") |
| 70 | + sys.exit(1) |
| 71 | + |
14 | 72 |
|
15 | 73 | argparser = argparse.ArgumentParser(
|
16 | 74 | prog="pegen", description="Experimental PEG-like parser generator"
|
|
23 | 81 | default=0,
|
24 | 82 | help="Print timing stats; repeat for more debug output",
|
25 | 83 | )
|
26 |
| -argparser.add_argument( |
27 |
| - "-c", "--cpython", action="store_true", help="Generate C code for inclusion into CPython" |
| 84 | +subparsers = argparser.add_subparsers(help="target language for the generated code") |
| 85 | + |
| 86 | +c_parser = subparsers.add_parser("c", help="Generate C code for inclusion into CPython") |
| 87 | +c_parser.set_defaults(func=generate_c_code) |
| 88 | +c_parser.add_argument("grammar_filename", help="Grammar description") |
| 89 | +c_parser.add_argument("tokens_filename", help="Tokens description") |
| 90 | +c_parser.add_argument( |
| 91 | + "-o", "--output", metavar="OUT", default="parse.c", help="Where to write the generated parser" |
28 | 92 | )
|
29 |
| -argparser.add_argument( |
| 93 | +c_parser.add_argument( |
30 | 94 | "--compile-extension",
|
31 | 95 | action="store_true",
|
32 | 96 | help="Compile generated C code into an extension module",
|
33 | 97 | )
|
34 |
| -argparser.add_argument( |
| 98 | +c_parser.add_argument( |
| 99 | + "--optimized", action="store_true", help="Compile the extension in optimized mode" |
| 100 | +) |
| 101 | +c_parser.add_argument( |
| 102 | + "--skip-actions", action="store_true", help="Suppress code emission for rule actions", |
| 103 | +) |
| 104 | + |
| 105 | +python_parser = subparsers.add_parser("python", help="Generate Python code") |
| 106 | +python_parser.set_defaults(func=generate_python_code) |
| 107 | +python_parser.add_argument("grammar_filename", help="Grammar description") |
| 108 | +python_parser.add_argument( |
35 | 109 | "-o",
|
36 | 110 | "--output",
|
37 | 111 | metavar="OUT",
|
38 |
| - help="Where to write the generated parser (default parse.py or parse.c)", |
| 112 | + default="parse.py", |
| 113 | + help="Where to write the generated parser", |
39 | 114 | )
|
40 |
| -argparser.add_argument("filename", help="Grammar description") |
41 |
| -argparser.add_argument( |
42 |
| - "--optimized", action="store_true", help="Compile the extension in optimized mode" |
43 |
| -) |
44 |
| -argparser.add_argument( |
| 115 | +python_parser.add_argument( |
45 | 116 | "--skip-actions", action="store_true", help="Suppress code emission for rule actions",
|
46 | 117 | )
|
47 | 118 |
|
48 | 119 |
|
49 | 120 | def main() -> None:
|
50 |
| - from pegen.build import build_parser_and_generator |
51 | 121 | from pegen.testutil import print_memstats
|
52 | 122 |
|
53 | 123 | args = argparser.parse_args()
|
54 |
| - verbose = args.verbose |
55 |
| - verbose_tokenizer = verbose >= 3 |
56 |
| - verbose_parser = verbose == 2 or verbose >= 4 |
57 |
| - t0 = time.time() |
58 |
| - |
59 |
| - output_file = args.output |
60 |
| - if not output_file: |
61 |
| - if args.cpython: |
62 |
| - output_file = "parse.c" |
63 |
| - else: |
64 |
| - output_file = "parse.py" |
65 |
| - |
66 |
| - try: |
67 |
| - grammar, parser, tokenizer, gen = build_parser_and_generator( |
68 |
| - args.filename, |
69 |
| - output_file, |
70 |
| - args.compile_extension, |
71 |
| - verbose_tokenizer, |
72 |
| - verbose_parser, |
73 |
| - args.verbose, |
74 |
| - keep_asserts_in_extension=False if args.optimized else True, |
75 |
| - skip_actions=args.skip_actions, |
76 |
| - ) |
77 |
| - except Exception as err: |
78 |
| - if args.verbose: |
79 |
| - raise # Show traceback |
80 |
| - traceback.print_exception(err.__class__, err, None) |
81 |
| - sys.stderr.write("For full traceback, use -v\n") |
| 124 | + if "func" not in args: |
| 125 | + argparser.print_help() |
82 | 126 | sys.exit(1)
|
83 | 127 |
|
| 128 | + t0 = time.time() |
| 129 | + grammar, parser, tokenizer, gen = args.func(args) |
| 130 | + t1 = time.time() |
| 131 | + |
84 | 132 | if not args.quiet:
|
85 | 133 | if args.verbose:
|
86 | 134 | print("Raw Grammar:")
|
@@ -110,8 +158,6 @@ def main() -> None:
|
110 | 158 | else:
|
111 | 159 | print()
|
112 | 160 |
|
113 |
| - t1 = time.time() |
114 |
| - |
115 | 161 | if args.verbose:
|
116 | 162 | dt = t1 - t0
|
117 | 163 | diag = tokenizer.diagnose()
|
|
0 commit comments