def ParseCommand(self, line): """Parses the next command from line and returns a list of ArgTokens. The parse stops at the first token that is not an ARG or FLAG. That token is not consumed. The caller can examine the return value to determine the parts of the line that were ignored and the remainder of the line that was not lexed/parsed yet. Args: line: a string containing the current command line Returns: A list of ArgTokens. """ self.tokens = lexer.GetShellTokens(line) self.cmd = self.root self.positionals_seen = 0 self.args = [] unknown = False while self.tokens: token = self.tokens.pop(0) value = token.UnquotedValue() if token.lex == lexer.ShellTokenType.FLAG: self.ParseFlag(token, value) elif token.lex == lexer.ShellTokenType.ARG and not unknown: if value in self.cmd[LOOKUP_COMMANDS]: self.cmd = self.cmd[LOOKUP_COMMANDS][value] if self.cmd[LOOKUP_IS_GROUP]: token_type = ArgTokenType.GROUP else: token_type = ArgTokenType.COMMAND self.args.append( ArgToken(value, token_type, self.cmd, token.start, token.end)) elif self.positionals_seen < len(self.cmd[LOOKUP_POSITIONALS]): positional = self.cmd[LOOKUP_POSITIONALS][ self.positionals_seen] self.args.append( ArgToken(value, ArgTokenType.POSITIONAL, positional, token.start, token.end)) if positional[LOOKUP_NARGS] not in ('*', '+'): self.positionals_seen += 1 elif not value: # trailing space break else: unknown = True if self.cmd == self.root: token_type = ArgTokenType.PREFIX else: token_type = ArgTokenType.UNKNOWN self.args.append( ArgToken(value, token_type, self.cmd, token.start, token.end)) elif token.lex == lexer.ShellTokenType.TERMINATOR: unknown = False self.cmd = self.root else: unknown = True self.args.append( ArgToken(value, ArgTokenType.UNKNOWN, self.cmd, token.start, token.end)) return self.args
def RunSubTest(self, s): return lexer.GetShellTokens(s)