| 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)
|