| 1 | #!/usr/bin/env python2
 | 
| 2 | """
 | 
| 3 | pgen2_demo.py
 | 
| 4 | """
 | 
| 5 | from __future__ import print_function
 | 
| 6 | 
 | 
| 7 | import os
 | 
| 8 | import sys
 | 
| 9 | 
 | 
| 10 | from _devbuild.gen import arith_nt
 | 
| 11 | from _devbuild.gen.syntax_asdl import source__Stdin
 | 
| 12 | 
 | 
| 13 | from core import alloc
 | 
| 14 | from core import error
 | 
| 15 | from frontend import reader
 | 
| 16 | from frontend import lexer
 | 
| 17 | from oil_lang import expr_parse
 | 
| 18 | from oil_lang import expr_to_ast
 | 
| 19 | 
 | 
| 20 | from mycpp import mylib
 | 
| 21 | from mycpp.mylib import log
 | 
| 22 | 
 | 
| 23 | from typing import Dict, Optional, TYPE_CHECKING
 | 
| 24 | if TYPE_CHECKING:
 | 
| 25 |     from pgen2.grammar import Grammar
 | 
| 26 |     from frontend.parse_lib import ParseContext
 | 
| 27 | 
 | 
| 28 | 
 | 
| 29 | def ParseDemo(oil_grammar):
 | 
| 30 |     # type: (Grammar) -> None
 | 
| 31 | 
 | 
| 32 |     arena = alloc.Arena()
 | 
| 33 |     arena.PushSource(source__Stdin(''))
 | 
| 34 | 
 | 
| 35 |     parse_ctx = None  # type: ParseContext
 | 
| 36 |     e_parser = expr_parse.ExprParser(parse_ctx, oil_grammar, False)
 | 
| 37 | 
 | 
| 38 |     line_lexer = lexer.LineLexer('', arena)
 | 
| 39 |     line_reader = reader.StringLineReader('1 + 2*3', arena)
 | 
| 40 |     lex = lexer.Lexer(line_lexer, line_reader)
 | 
| 41 | 
 | 
| 42 |     try:
 | 
| 43 |         pnode, _ = e_parser.Parse(lex, arith_nt.arith_expr)
 | 
| 44 |     except error.Parse as e:
 | 
| 45 |         #ui.PrettyPrintError(e, arena)
 | 
| 46 |         log("Parse Error (TODO: print it)")
 | 
| 47 |         return
 | 
| 48 | 
 | 
| 49 |     # TODO: Fill this in.  Oil uses parse_lib.MakeGrammarNames()
 | 
| 50 |     #
 | 
| 51 |     # terminals: _Id_str?  Doesn't work in mycpp
 | 
| 52 |     # nonterminals: gr.number2symbol.  Is this ever used at runtime?
 | 
| 53 |     #
 | 
| 54 |     # Dict[int,str] should really be a List[str] then?
 | 
| 55 | 
 | 
| 56 |     if 0:
 | 
| 57 |         names = {}  # type: Dict[int, str]
 | 
| 58 |         printer = expr_parse.ParseTreePrinter(names)
 | 
| 59 |         printer.Print(pnode)
 | 
| 60 |         # NOTE: Could also transform
 | 
| 61 | 
 | 
| 62 |     # This only works for Oil
 | 
| 63 |     if 0:
 | 
| 64 |         tr = expr_to_ast.Transformer(oil_grammar)
 | 
| 65 |         node = tr.Expr(pnode)
 | 
| 66 | 
 | 
| 67 |         assert node is not None
 | 
| 68 | 
 | 
| 69 |         tree = node.AbbreviatedTree()
 | 
| 70 |         fmt.PrintTree(tree, mylib.Stdout())
 | 
| 71 | 
 | 
| 72 | 
 | 
| 73 | def run_tests():
 | 
| 74 |     # type: () -> None
 | 
| 75 | 
 | 
| 76 |     if mylib.CPP:
 | 
| 77 |         # TODO: Initialize this
 | 
| 78 |         gr = None  # type: Optional[Grammar]
 | 
| 79 |     else:
 | 
| 80 |         # And then cppgen_pass.py gets rid of all the "else" blocks
 | 
| 81 | 
 | 
| 82 |         from pgen2 import grammar
 | 
| 83 | 
 | 
| 84 |         # We're finding a bad os.pyi ?
 | 
| 85 |         repo_root = os.environ['HOME'] + '/git/oilshell/oil'  # type: ignore
 | 
| 86 |         gr = grammar.Grammar()
 | 
| 87 |         f = open(repo_root + '/_devbuild/gen/arith.marshal')
 | 
| 88 |         contents = f.read()
 | 
| 89 |         gr.loads(contents)
 | 
| 90 |         f.close()
 | 
| 91 | 
 | 
| 92 |     ParseDemo(gr)
 | 
| 93 |     print('done')
 | 
| 94 | 
 | 
| 95 | 
 | 
| 96 | def run_benchmarks():
 | 
| 97 |     # type: () -> None
 | 
| 98 |     pass
 | 
| 99 | 
 | 
| 100 | 
 | 
| 101 | if __name__ == '__main__':
 | 
| 102 |     if os.getenv('BENCHMARK'):
 | 
| 103 |         log('Benchmarking...')
 | 
| 104 |         run_benchmarks()
 | 
| 105 |     else:
 | 
| 106 |         run_tests()
 |