private ExpressionAst GetCommandArgument(CommandArgumentContext context, Token token) { Diagnostics.Assert(token.Kind != TokenKind.Comma, "A unary comma is an error in command mode, and should have already been reported."); ExpressionAst exprAst; List<ExpressionAst> commandArgs = null; Token commaToken = null; bool foundVerbatimArgument = false; while (true) { switch (token.Kind) { // The following tokens are never allowed as command arguments. case TokenKind.Pipe: case TokenKind.RCurly: case TokenKind.RParen: case TokenKind.EndOfInput: case TokenKind.NewLine: case TokenKind.Semi: case TokenKind.Redirection: case TokenKind.RedirectInStd: case TokenKind.AndAnd: case TokenKind.OrOr: case TokenKind.Ampersand: case TokenKind.MinusMinus: case TokenKind.Comma: UngetToken(token); // If we haven't seen an argument, the caller must issue an error. If we've seen at least one // argument, then we will issue the error and return back the arguments seen so far. if (commaToken == null) { return null; } // ErrorRecovery: stop looking for additional arguments, exclude the trailing comma ReportIncompleteInput(After(commaToken), () => ParserStrings.MissingExpression, ","); return new ErrorExpressionAst(ExtentOf(commandArgs.First(), commaToken), commandArgs); case TokenKind.SplattedVariable: case TokenKind.Variable: case TokenKind.Number: case TokenKind.HereStringExpandable: case TokenKind.StringExpandable: case TokenKind.HereStringLiteral: case TokenKind.StringLiteral: case TokenKind.LParen: case TokenKind.DollarParen: case TokenKind.AtParen: case TokenKind.AtCurly: case TokenKind.LCurly: UngetToken(token); exprAst = PrimaryExpressionRule(withMemberAccess: true); Diagnostics.Assert(exprAst != null, "PrimaryExpressionRule should never return null"); break; case TokenKind.Generic: if ((context & CommandArgumentContext.CommandName) != 0) { token.TokenFlags |= TokenFlags.CommandName; } var genericToken = (StringToken)token; var expandableToken = genericToken as StringExpandableToken; // A command name w/o invocation operator is not expandable even if the token has expandable parts // If we have seen an invocation operator, the command name is expandable. if (expandableToken != null && context != CommandArgumentContext.CommandName) { var nestedExpressions = ParseNestedExpressions(expandableToken); exprAst = new ExpandableStringExpressionAst(expandableToken, expandableToken.Value, expandableToken.FormatString, nestedExpressions); } else { exprAst = new StringConstantExpressionAst(genericToken.Extent, genericToken.Value, StringConstantType.BareWord); // If this is a verbatim argument, then don't continue peeking if (String.Equals(genericToken.Value, VERBATIM_ARGUMENT, StringComparison.OrdinalIgnoreCase)) { foundVerbatimArgument = true; } } break; default: exprAst = new StringConstantExpressionAst(token.Extent, token.Text, StringConstantType.BareWord); // A command/argument that matches a keyword isn't really a keyword, so don't color it that way token.TokenFlags &= ~TokenFlags.Keyword; switch (context) { case CommandArgumentContext.CommandName: case CommandArgumentContext.CommandNameAfterInvocationOperator: token.TokenFlags |= TokenFlags.CommandName; break; case CommandArgumentContext.FileName: case CommandArgumentContext.CommandArgument: case CommandArgumentContext.SwitchCondition: token.SetIsCommandArgument(); break; } break; } if (context != CommandArgumentContext.CommandArgument) { break; } if (foundVerbatimArgument) { break; } token = PeekToken(); if (token.Kind != TokenKind.Comma) { break; } commaToken = token; if (commandArgs == null) { commandArgs = new List<ExpressionAst>(); } commandArgs.Add(exprAst); SkipToken(); SkipNewlines(); token = NextToken(); } Diagnostics.Assert(commandArgs != null || exprAst != null, "How did that happen?"); if (commandArgs != null) { commandArgs.Add(exprAst); return new ArrayLiteralAst(ExtentOf(commandArgs[0], commandArgs[commandArgs.Count - 1]), commandArgs); } return exprAst; }
private ExpressionAst GetCommandArgument(CommandArgumentContext context, Token token) { ExpressionAst ast; List<ExpressionAst> source = null; Token token2 = null; bool flag = false; Label_0006: switch (token.Kind) { case TokenKind.Variable: case TokenKind.SplattedVariable: case TokenKind.Number: case TokenKind.StringLiteral: case TokenKind.StringExpandable: case TokenKind.HereStringLiteral: case TokenKind.HereStringExpandable: case TokenKind.LParen: case TokenKind.LCurly: case TokenKind.AtParen: case TokenKind.AtCurly: case TokenKind.DollarParen: this.UngetToken(token); ast = this.PrimaryExpressionRule(true); break; case TokenKind.Generic: { if ((context & CommandArgumentContext.CommandName) != 0) { token.TokenFlags |= TokenFlags.CommandName; } StringToken token3 = (StringToken)token; StringExpandableToken expandableStringToken = token3 as StringExpandableToken; if ((expandableStringToken != null) && (context != CommandArgumentContext.CommandName)) { List<ExpressionAst> nestedExpressions = this.ParseNestedExpressions(expandableStringToken); ast = new ExpandableStringExpressionAst(expandableStringToken, expandableStringToken.Value, expandableStringToken.FormatString, nestedExpressions); } else { ast = new StringConstantExpressionAst(token3.Extent, token3.Value, StringConstantType.BareWord); if (string.Equals(token3.Value, "--%", StringComparison.OrdinalIgnoreCase)) { flag = true; } } break; } case TokenKind.NewLine: case TokenKind.EndOfInput: case TokenKind.RParen: case TokenKind.RCurly: case TokenKind.Semi: case TokenKind.AndAnd: case TokenKind.OrOr: case TokenKind.Ampersand: case TokenKind.Pipe: case TokenKind.Comma: case TokenKind.MinusMinus: case TokenKind.Redirection: case TokenKind.RedirectInStd: this.UngetToken(token); if (token2 != null) { this.ReportIncompleteInput(After(token2), ParserStrings.MissingExpression, new object[] { "," }); return new ErrorExpressionAst(ExtentOf(source.First<ExpressionAst>(), token2), (IEnumerable<Ast>)source); } return null; default: ast = new StringConstantExpressionAst(token.Extent, token.Text, StringConstantType.BareWord); switch (context) { case CommandArgumentContext.CommandName: case CommandArgumentContext.CommandNameAfterInvocationOperator: token.TokenFlags |= TokenFlags.CommandName; break; case CommandArgumentContext.FileName: case CommandArgumentContext.CommandArgument: case CommandArgumentContext.SwitchCondition: token.SetIsCommandArgument(); break; } break; } if ((context == CommandArgumentContext.CommandArgument) && !flag) { token = this.PeekToken(); if (token.Kind == TokenKind.Comma) { token2 = token; if (source == null) { source = new List<ExpressionAst>(); } source.Add(ast); this.SkipToken(); this.SkipNewlines(); token = this.NextToken(); goto Label_0006; } } if (source != null) { source.Add(ast); return new ArrayLiteralAst(ExtentOf(source.First<ExpressionAst>(), source.Last<ExpressionAst>()), source); } return ast; }
private ExpressionAst GetSingleCommandArgument(CommandArgumentContext context) { if (PeekToken().Kind == TokenKind.Comma || PeekToken().Kind == TokenKind.EndOfInput) { return null; } var oldTokenizerMode = _tokenizer.Mode; try { SetTokenizerMode(TokenizerMode.Command); return GetCommandArgument(context, NextToken()); } finally { SetTokenizerMode(oldTokenizerMode); } }