1 | #!/usr/bin/env python2
|
2 | """Osh_parse.py."""
|
3 | from __future__ import print_function
|
4 |
|
5 | import sys
|
6 |
|
7 | from _devbuild.gen.option_asdl import option_i
|
8 | from _devbuild.gen.syntax_asdl import source, source_t, command, command_t
|
9 | from asdl import format as fmt
|
10 | from core import alloc
|
11 | from core import error
|
12 | from core import optview
|
13 | #from core import main_loop
|
14 | from core import pyutil
|
15 | from core import state
|
16 | from core import ui
|
17 | from frontend import parse_lib
|
18 | from frontend import reader
|
19 | from mycpp import mylib
|
20 | from mycpp.mylib import log
|
21 |
|
22 | _ = log
|
23 |
|
24 | from typing import List, Dict, TYPE_CHECKING
|
25 | if TYPE_CHECKING:
|
26 | from osh.cmd_parse import CommandParser
|
27 | from pgen2.grammar import Grammar
|
28 |
|
29 |
|
30 | # TEMP: Copied from core/main_loop.py
|
31 | def ParseWholeFile(c_parser):
|
32 | # type: (CommandParser) -> command_t
|
33 | """Parse an entire shell script.
|
34 |
|
35 | This uses the same logic as Batch().
|
36 | """
|
37 | children = [] # type: List[command_t]
|
38 | while True:
|
39 | node = c_parser.ParseLogicalLine() # can raise ParseError
|
40 | if node is None: # EOF
|
41 | c_parser.CheckForPendingHereDocs() # can raise ParseError
|
42 | break
|
43 | children.append(node)
|
44 |
|
45 | if len(children) == 1:
|
46 | return children[0]
|
47 | else:
|
48 | return command.CommandList(children)
|
49 |
|
50 |
|
51 | def main(argv):
|
52 | # type: (List[str]) -> int
|
53 | arena = alloc.Arena()
|
54 | errfmt = ui.ErrorFormatter()
|
55 |
|
56 | opt0_array = state.InitOpts()
|
57 | no_stack = None # type: List[bool] # for mycpp
|
58 | opt_stacks = [no_stack] * option_i.ARRAY_SIZE # type: List[List[bool]]
|
59 | parse_opts = optview.Parse(opt0_array, opt_stacks)
|
60 | # Dummy value; not respecting aliases!
|
61 | aliases = {} # type: Dict[str, str]
|
62 | # parse `` and a[x+1]=bar differently
|
63 |
|
64 | ysh_grammar = None # type: Grammar
|
65 | if mylib.PYTHON:
|
66 | loader = pyutil.GetResourceLoader()
|
67 | ysh_grammar = pyutil.LoadYshGrammar(loader)
|
68 |
|
69 | parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, ysh_grammar)
|
70 |
|
71 | pretty_print = True
|
72 |
|
73 | if len(argv) == 1:
|
74 | line_reader = reader.FileLineReader(mylib.Stdin(), arena)
|
75 | src = source.Stdin('') # type: source_t
|
76 |
|
77 | elif len(argv) == 2:
|
78 | path = argv[1]
|
79 | f = mylib.open(path)
|
80 | line_reader = reader.FileLineReader(f, arena)
|
81 | src = source.MainFile(path)
|
82 |
|
83 | elif len(argv) == 3:
|
84 | if argv[1] == '-c':
|
85 | # This path is easier to run through GDB
|
86 | line_reader = reader.StringLineReader(argv[2], arena)
|
87 | src = source.CFlag
|
88 |
|
89 | elif argv[1] == '-n': # For benchmarking, allow osh_parse -n file.txt
|
90 | path = argv[2]
|
91 | f = mylib.open(path)
|
92 | line_reader = reader.FileLineReader(f, arena)
|
93 | src = source.MainFile(path)
|
94 | # This is like --ast-format none, which benchmarks/osh-helper.sh passes.
|
95 | pretty_print = False
|
96 |
|
97 | else:
|
98 | raise AssertionError()
|
99 |
|
100 | else:
|
101 | raise AssertionError()
|
102 |
|
103 | arena.PushSource(src)
|
104 |
|
105 | c_parser = parse_ctx.MakeOshParser(line_reader)
|
106 |
|
107 | try:
|
108 | #node = main_loop.ParseWholeFile(c_parser)
|
109 | node = ParseWholeFile(c_parser)
|
110 | except error.Parse as e:
|
111 | errfmt.PrettyPrintError(e)
|
112 | return 2
|
113 | assert node is not None
|
114 |
|
115 | # C++ doesn't have the abbreviations yet
|
116 | #tree = node.AbbreviatedTree()
|
117 | if pretty_print:
|
118 | tree = node.PrettyTree()
|
119 |
|
120 | ast_f = fmt.DetectConsoleOutput(mylib.Stdout())
|
121 | fmt.PrintTree(tree, ast_f)
|
122 | ast_f.write('\n')
|
123 |
|
124 | return 0
|
125 |
|
126 |
|
127 | if __name__ == '__main__':
|
128 | try:
|
129 | main(sys.argv)
|
130 | except RuntimeError as e:
|
131 | print('FATAL: %s' % e, file=sys.stderr)
|
132 | sys.exit(1)
|