def _assertReadWordFailure(test, word_str): print('\n---', word_str) w_parser = InitWordParser(word_str) w = w_parser.ReadWord(LexMode.OUTER) if w: ast.PrettyPrint(w) test.fail('Expected a parser error, got %r' % w) else: print(w_parser.Error())
def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader): # Is this correct? Are there any non-ANSI terminals? I guess you can pass # -i but redirect stdout. if opts.ast_output == '-': ast_f = fmt.DetectConsoleOutput(sys.stdout) elif opts.ast_output == '-': f = open(opts.ast_output, 'w') # implicitly closed when the process ends ast_f = fmt.DetectConsoleOutput(f) else: ast_f = None while True: try: w = c_parser.Peek() except KeyboardInterrupt: print('Ctrl-C') break if w is None: raise RuntimeError('Failed parse: %s' % c_parser.Error()) c_id = word.CommandId(w) if c_id == Id.Op_Newline: print('nothing to execute') elif c_id == Id.Eof_Real: print('EOF') break else: node = c_parser.ParseCommandLine() # TODO: Need an error for an empty command, which we ignore? GetLine # could do that in the first position? # ParseSimpleCommand fails with '\n' token? if not node: # TODO: PrintError here raise RuntimeError('failed parse: %s' % c_parser.Error()) if ast_f: ast.PrettyPrint(node) status = ex.Execute(node) if opts.print_status: print('STATUS', repr(status)) # Reset prompt and clear memory. TODO: If there are any function # definitions ANYWHERE in the node, you should not clear the underlying # memory. We still need to execute those strings! line_reader.Reset() # Reset internal newline state. # NOTE: It would actually be correct to reinitialize all objects (except # Env) on every iteration. But we know that the w_parser is the only thing # that needs to be reset, for now. w_parser.Reset() c_parser.Reset()
def _assertParseCommandListError(test, code_str): arena, c_parser = InitCommandParser(code_str) node = c_parser.ParseCommandLine() if node: print('UNEXPECTED:') ast.PrettyPrint(node) test.fail("Expected %r to fail" % code_str) return err = c_parser.Error() #print(err) ui.PrintErrorStack(err, arena, sys.stdout)
def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader): if opts.show_ast: ast_f = fmt.DetectConsoleOutput(sys.stdout) else: ast_f = None while True: try: w = c_parser.Peek() except KeyboardInterrupt: print('Ctrl-C') break if w is None: raise RuntimeError('Failed parse: %s' % c_parser.Error()) c_id = word.CommandId(w) if c_id == Id.Op_Newline: print('nothing to execute') elif c_id == Id.Eof_Real: print('EOF') break else: node = c_parser.ParseCommandLine() # TODO: Need an error for an empty command, which we ignore? GetLine # could do that in the first position? # ParseSimpleCommand fails with '\n' token? if not node: # TODO: PrintError here raise RuntimeError('failed parse: %s' % c_parser.Error()) if ast_f: ast.PrettyPrint(node) status = ex.Execute(node) if opts.print_status: print('STATUS', repr(status)) # Reset prompt to PS1. line_reader.Reset() # Reset internal newline state. # NOTE: It would actually be correct to reinitialize all objects (except # Env) on every iteration. But we know that the w_parser is the only thing # that needs to be reset, for now. w_parser.Reset() c_parser.Reset()
def _assertReadWordWithArena(test, word_str): print('\n---', word_str) arena, w_parser = _InitWordParserWithArena(word_str) w = w_parser.ReadWord(LexMode.OUTER) if w: ast.PrettyPrint(w) else: err = w_parser.Error() test.fail("Couldn't parse %r: %s" % (word_str, err)) # Next word must be \n w2 = w_parser.ReadWord(LexMode.OUTER) test.assertTrue( TokenWordsEqual(ast.TokenWord(ast.token(Id.Op_Newline, '\n')), w2)) return arena, w
def testReadArith(self): CASES = [ '1 + 2', 'a + b', '$a * $b', '${a} * ${b}', '$(echo 1) * $(echo 2)', '`echo 1` + 2', '$((1 + 2)) * $((3 + 4))', "'single quoted'", # Allowed by oil but not bash '"${a}" + "${b}"', # Ditto '$# + $$', # This doesn't work but does in bash -- should be 15 #'$(( $(echo 1)$(echo 2) + 3 ))', '$(( x[0] < 5 ))', '$(( ++i ))', '$(( i++ ))', '$(( x -= 1))', '$(( x |= 1))', '$(( x[0] = 1 ))', '$(( 1 | 0 ))', '$((0x$size))', ] for expr in CASES: print('---') print(expr) print() w_parser = InitWordParser(expr) w_parser._Next(LexMode.ARITH) # Can we remove this requirement? while True: w = w_parser.ReadWord(LexMode.ARITH) if not w: err = w_parser.Error() print('ERROR', err) self.fail(err) break ast.PrettyPrint(w) if word.CommandId(w) in (Id.Eof_Real, Id.Unknown_Tok): break
def _assertParseMethod(test, code_str, method, expect_success=True): arena, c_parser = InitCommandParser(code_str) m = getattr(c_parser, method) node = m() if node: ast.PrettyPrint(node) if not expect_success: test.fail('Expected %r to fail ' % code_str) else: # TODO: Could copy PrettyPrintError from pysh.py err = c_parser.Error() print(err) ui.PrintErrorStack(err, arena, sys.stdout) if expect_success: test.fail('%r failed' % code_str) return node
def _assertReadWordWithArena(test, word_str): print('\n---', word_str) arena, w_parser = _InitWordParserWithArena(word_str) w = w_parser.ReadWord(lex_mode_e.OUTER) if w: ast.PrettyPrint(w) else: err = w_parser.Error() test.fail("Couldn't parse %r: %s" % (word_str, err)) # Next word must be Eof_Real w2 = w_parser.ReadWord(lex_mode_e.OUTER) test.assertTrue( test_lib.TokenWordsEqual(ast.TokenWord(ast.token(Id.Eof_Real, '')), w2), w2) return arena, w
def testRead(self): CASES = [ 'ls "foo"', '$(( 1 + 2 ))', '$(echo $(( 1 )) )', # OLD BUG: arith sub within command sub 'echo ${#array[@]} b', # Had a bug here 'echo $(( ${#array[@]} ))', # Bug here # Had a bug: unary minus #'${mounted_disk_regex:0:-1}', 'echo ${@%suffix}', # had a bug here '${@}', 'echo ${var,,}', 'echo ${var,,?}', # Line continuation tests '${\\\nfoo}', # VS_1 '${foo\\\n}', # VS_2 '${foo#\\\nyo}', # VS_ARG_UNQ '"${foo#\\\nyo}"', # VS_ARG_DQ ] for expr in CASES: print('---') print(expr) print() w_parser = InitWordParser(expr) while True: w = w_parser.ReadWord(LexMode.OUTER) if w is None: e = w_parser.Error() print('Error in word parser: %s' % e) self.fail(e) ast.PrettyPrint(w) if word.CommandId(w) == Id.Eof_Real: break