def _ReadArithExpr(self): # type: () -> arith_expr_t """Read and parse an arithmetic expression in various contexts. $(( 1+2 )) (( a=1+2 )) ${a[ 1+2 ]} ${a : 1+2 : 1+2} See tests/arith-context.test.sh for ambiguous cases. ${a[a[0]]} is valid # VS_RBRACKET vs Id.Arith_RBracket ${s : a<b?0:1 : 1} # VS_COLON vs Id.Arith_Colon TODO: Instead of having an eof_type. I think we should use just run the arith parser until it's done. That will take care of both : and ]. We switch the state back. See the assertion in ArithParser.Parse() -- unexpected extra input. """ # calls self.ReadWord(lex_mode_e.Arith) a_parser = tdop.TdopParser(arith_parse.Spec(), self, self.parse_opts) anode = a_parser.Parse() return anode
def MakeArithParser(self, code_str): # type: (str) -> TdopParser """Used for a[x+1]=foo in the CommandParser.""" line_reader = reader.StringLineReader(code_str, self.arena) lx = self._MakeLexer(line_reader) w_parser = word_parse.WordParser(self, lx, line_reader) w_parser.Init(lex_mode_e.Arith) # Special initialization a_parser = tdop.TdopParser(arith_parse.Spec(), w_parser, self.parse_opts) return a_parser
def main(argv): spec = arith_parse.Spec() print("""\ #include "osh_arith_parse.h" using syntax_asdl::arith_expr_t; using syntax_asdl::word_t; using tdop::TdopParser; """) to_declare = collections.defaultdict(set) for row in spec.nud_lookup.itervalues(): mod_name, func_name = row.ModuleAndFuncName() to_declare[mod_name].add(('N', func_name)) log('') log('') # TODO: namespace are arith_parse or tdop for row in spec.led_lookup.itervalues(): mod_name, func_name = row.ModuleAndFuncName() to_declare[mod_name].add(('L', func_name)) # main program has no headers, so here are prototypes for mod_name in to_declare: print('namespace %s { ' % mod_name) for typ, func in sorted(to_declare[mod_name]): if typ == 'N': # tdop::NullFunc fmt = 'arith_expr_t* %s(TdopParser*, word_t*, int);' else: # tdop::LeftFunc fmt = 'arith_expr_t* %s(TdopParser*, word_t*, arith_expr_t*, int);' print(fmt % func) print('}') print('') print("""\ namespace arith_parse { tdop::LeftInfo kLeftLookup[] = { { nullptr, 0, 0 }, // empty """, end='') n = max(spec.led_lookup) m = max(spec.nud_lookup) assert n == m log('arith_parse_gen.py: precedence table has %d entries', n) for i in xrange(1, n): row = spec.led_lookup.get(i) if row is None: assert False, 'No empty rows anymore' print(' { nullptr, 0, 0 }, // empty') else: print(' %s' % row) print("""\ }; tdop::NullInfo kNullLookup[] = { { nullptr, 0 }, // empty """, end='') for i in xrange(1, n): row = spec.nud_lookup.get(i) if row is None: assert False, 'No empty rows anymore' print(' { nullptr, 0 }, // empty') else: print(' %s' % row) print("""\ }; }; """)