internal CommandBaseAst CommandRule() { Token token; bool flag; bool flag2; IScriptExtent extent; bool flag3 = false; bool flag4 = false; RedirectionAst[] redirections = null; List<CommandElementAst> elements = new List<CommandElementAst>(); TokenizerMode mode = this._tokenizer.Mode; try { CommandArgumentContext commandNameAfterInvoationOperator; this.SetTokenizerMode(TokenizerMode.Command); Token first = this.NextToken(); token = first; extent = first.Extent; flag = false; flag2 = false; if (first.Kind == TokenKind.Dot) { flag = true; first = this.NextToken(); commandNameAfterInvoationOperator = CommandArgumentContext.CommandNameAfterInvocationOperator; } else if (first.Kind == TokenKind.Ampersand) { flag2 = true; first = this.NextToken(); commandNameAfterInvoationOperator = CommandArgumentContext.CommandNameAfterInvocationOperator; } else { commandNameAfterInvoationOperator = CommandArgumentContext.CommandName; } bool flag5 = true; while (flag5) { switch (first.Kind) { case TokenKind.Parameter: if (((commandNameAfterInvoationOperator & CommandArgumentContext.CommandName) != 0) || flag3) { extent = first.Extent; first.TokenFlags |= TokenFlags.CommandName; StringConstantExpressionAst item = new StringConstantExpressionAst(first.Extent, first.Text, StringConstantType.BareWord); elements.Add(item); } else { ExpressionAst commandArgument; IScriptExtent extent2; ParameterToken token3 = (ParameterToken) first; if (token3.UsedColon && (this.PeekToken().Kind != TokenKind.Comma)) { commandArgument = this.GetCommandArgument(CommandArgumentContext.CommandArgument, this.NextToken()); if (commandArgument == null) { extent2 = token3.Extent; this.ReportError(After(extent2), ParserStrings.ParameterRequiresArgument, new object[] { token3.Text }); } else { extent2 = ExtentOf(first, commandArgument); } } else { commandArgument = null; extent2 = first.Extent; } extent = extent2; CommandParameterAst ast3 = new CommandParameterAst(extent2, token3.ParameterName, commandArgument, first.Extent); elements.Add(ast3); } goto Label_0404; case TokenKind.NewLine: case TokenKind.RParen: case TokenKind.RCurly: case TokenKind.Semi: case TokenKind.AndAnd: case TokenKind.OrOr: case TokenKind.Pipe: case TokenKind.EndOfInput: { this.UngetToken(first); flag5 = false; continue; } case TokenKind.Ampersand: extent = first.Extent; this.ReportError(first.Extent, ParserStrings.MissingArgument, new object[0]); goto Label_0404; case TokenKind.Comma: extent = first.Extent; this.ReportError(first.Extent, ParserStrings.MissingArgument, new object[0]); this.SkipNewlines(); goto Label_0404; case TokenKind.MinusMinus: extent = first.Extent; elements.Add(flag3 ? ((CommandElementAst) new StringConstantExpressionAst(first.Extent, first.Text, StringConstantType.BareWord)) : ((CommandElementAst) new CommandParameterAst(first.Extent, "-", null, first.Extent))); flag3 = true; goto Label_0404; case TokenKind.Redirection: case TokenKind.RedirectInStd: if ((commandNameAfterInvoationOperator & CommandArgumentContext.CommandName) != 0) { break; } if (redirections == null) { redirections = new RedirectionAst[7]; } this.RedirectionRule((RedirectionToken) first, redirections, ref extent); goto Label_0404; default: { if ((first.Kind == TokenKind.InlineScript) && (commandNameAfterInvoationOperator == CommandArgumentContext.CommandName)) { flag5 = this.InlineScriptRule(first, elements); extent = elements.Last<CommandElementAst>().Extent; if (flag5) { goto Label_0404; } continue; } ExpressionAst ast4 = this.GetCommandArgument(commandNameAfterInvoationOperator, first); StringToken token4 = first as StringToken; if ((token4 != null) && string.Equals(token4.Value, "--%", StringComparison.OrdinalIgnoreCase)) { elements.Add(ast4); extent = ast4.Extent; StringToken verbatimCommandArgumentToken = this.GetVerbatimCommandArgumentToken(); if (verbatimCommandArgumentToken != null) { flag4 = true; flag5 = false; ast4 = new StringConstantExpressionAst(verbatimCommandArgumentToken.Extent, verbatimCommandArgumentToken.Value, StringConstantType.BareWord); elements.Add(ast4); extent = ast4.Extent; } } else { extent = ast4.Extent; elements.Add(ast4); } goto Label_0404; } } extent = first.Extent; elements.Add(new StringConstantExpressionAst(first.Extent, first.Text, StringConstantType.BareWord)); Label_0404: if (!flag4) { commandNameAfterInvoationOperator = CommandArgumentContext.CommandArgument; first = this.NextToken(); } } } finally { this.SetTokenizerMode(mode); } if (elements.Count == 0) { if (flag || flag2) { IScriptExtent extent3 = token.Extent; this.ReportError(extent3, ParserStrings.MissingExpression, new object[] { token.Text }); return new CommandExpressionAst(extent3, new ErrorExpressionAst(extent3, null), null); } return null; } return new CommandAst(ExtentOf(token, extent), elements, (flag || flag2) ? token.Kind : TokenKind.Unknown, (redirections != null) ? redirections.Where<RedirectionAst>(r => r != null) : null); }
private static CommandRedirection GetCommandRedirection(RedirectionAst redirectionAst, System.Management.Automation.ExecutionContext context) { FileRedirectionAst ast = redirectionAst as FileRedirectionAst; if (ast != null) { object obj2 = Compiler.GetExpressionValue(ast.Location, context, (IList)null); return new FileRedirection(ast.FromStream, ast.Append, obj2.ToString()); } MergingRedirectionAst ast2 = (MergingRedirectionAst) redirectionAst; return new MergingRedirection(ast2.FromStream, ast2.ToStream); }
private RedirectionAst RedirectionRule(RedirectionToken redirectionToken, RedirectionAst[] redirections, ref IScriptExtent extent) { RedirectionAst fileRedirectionAst; string allStream; FileRedirectionToken fileRedirectionToken = redirectionToken as FileRedirectionToken; if (fileRedirectionToken != null || redirectionToken as InputRedirectionToken != null) { ExpressionAst singleCommandArgument = this.GetSingleCommandArgument(Parser.CommandArgumentContext.FileName); if (singleCommandArgument == null) { this.ReportError(Parser.After(redirectionToken), ParserStrings.MissingFileSpecification, new object[0]); singleCommandArgument = new ErrorExpressionAst(redirectionToken.Extent, null); } if (fileRedirectionToken != null) { fileRedirectionAst = new FileRedirectionAst(Parser.ExtentOf(fileRedirectionToken, singleCommandArgument), fileRedirectionToken.FromStream, singleCommandArgument, fileRedirectionToken.Append); } else { object[] text = new object[1]; text[0] = redirectionToken.Text; this.ReportError(redirectionToken.Extent, ParserStrings.RedirectionNotSupported, text); extent = Parser.ExtentOf(redirectionToken, singleCommandArgument); return null; } } else { MergingRedirectionToken mergingRedirectionToken = (MergingRedirectionToken)redirectionToken; RedirectionStream fromStream = mergingRedirectionToken.FromStream; RedirectionStream toStream = mergingRedirectionToken.ToStream; if (toStream == RedirectionStream.Output) { if (fromStream == toStream) { object[] objArray = new object[1]; objArray[0] = mergingRedirectionToken.Text; this.ReportError(redirectionToken.Extent, ParserStrings.RedirectionNotSupported, objArray); } } else { object[] text1 = new object[1]; text1[0] = mergingRedirectionToken.Text; this.ReportError(redirectionToken.Extent, ParserStrings.RedirectionNotSupported, text1); toStream = RedirectionStream.Output; } fileRedirectionAst = new MergingRedirectionAst(mergingRedirectionToken.Extent, mergingRedirectionToken.FromStream, toStream); } if (redirections[(int)fileRedirectionAst.FromStream] != null) { RedirectionStream redirectionStream = fileRedirectionAst.FromStream; if (redirectionStream == RedirectionStream.All) { allStream = ParserStrings.AllStream; } else if (redirectionStream == RedirectionStream.Output) { allStream = ParserStrings.OutputStream; } else if (redirectionStream == RedirectionStream.Error) { allStream = ParserStrings.ErrorStream; } else if (redirectionStream == RedirectionStream.Warning) { allStream = ParserStrings.WarningStream; } else if (redirectionStream == RedirectionStream.Verbose) { allStream = ParserStrings.VerboseStream; } else if (redirectionStream == RedirectionStream.Debug) { allStream = ParserStrings.DebugStream; } else if (redirectionStream == RedirectionStream.Host) { allStream = ParserStrings.HostStream; } else { throw PSTraceSource.NewArgumentOutOfRangeException("result.FromStream", (object)fileRedirectionAst.FromStream); } object[] objArray1 = new object[1]; objArray1[0] = allStream; this.ReportError(fileRedirectionAst.Extent, ParserStrings.StreamAlreadyRedirected, objArray1); } else { redirections[(int)fileRedirectionAst.FromStream] = fileRedirectionAst; } extent = fileRedirectionAst.Extent; return fileRedirectionAst; }
private PipelineBaseAst PipelineRule() { List<CommandBaseAst> source = new List<CommandBaseAst>(); IScriptExtent first = null; Token token = null; bool flag = true; while (flag) { CommandBaseAst ast; ExpressionAst ast2; Token token2 = null; TokenizerMode mode = this._tokenizer.Mode; try { this.SetTokenizerMode(TokenizerMode.Expression); ast2 = this.ExpressionRule(); if (ast2 != null) { Token token3 = this.PeekToken(); if (token3.Kind.HasTrait(TokenFlags.AssignmentOperator)) { this.SkipToken(); token2 = token3; } } } finally { this.SetTokenizerMode(mode); } if (ast2 != null) { if (source.Any<CommandBaseAst>()) { this.ReportError(ast2.Extent, ParserStrings.ExpressionsMustBeFirstInPipeline, new object[0]); } if (token2 != null) { this.SkipNewlines(); StatementAst right = this.StatementRule(); if (right == null) { IScriptExtent extent2 = After(token2); this.ReportIncompleteInput(extent2, ParserStrings.ExpectedValueExpression, new object[] { token2.Kind.Text() }); right = new ErrorStatementAst(extent2, (IEnumerable<Ast>)null); } return new AssignmentStatementAst(ExtentOf((Ast)ast2, (Ast)right), ast2, token2.Kind, right, token2.Extent); } RedirectionAst[] redirections = null; RedirectionToken redirectionToken = this.PeekToken() as RedirectionToken; RedirectionAst ast4 = null; while (redirectionToken != null) { this.SkipToken(); if (redirections == null) { redirections = new RedirectionAst[7]; } IScriptExtent extent3 = null; ast4 = this.RedirectionRule(redirectionToken, redirections, ref extent3); redirectionToken = this.PeekToken() as RedirectionToken; } IScriptExtent extent = (ast4 != null) ? ExtentOf((Ast)ast2, (Ast)ast4) : ast2.Extent; ast = new CommandExpressionAst(extent, ast2, (redirections != null) ? (from r in redirections where r != null select r) : null); } else { ast = this.CommandRule(); } if (ast != null) { if (first == null) { first = ast.Extent; } source.Add(ast); } else if (source.Any<CommandBaseAst>() || (this.PeekToken().Kind == TokenKind.Pipe)) { IScriptExtent extent5 = (token != null) ? After(token) : this.PeekToken().Extent; this.ReportIncompleteInput(extent5, ParserStrings.EmptyPipeElement, new object[0]); } token = this.PeekToken(); switch (token.Kind) { case TokenKind.NewLine: case TokenKind.EndOfInput: case TokenKind.RParen: case TokenKind.RCurly: case TokenKind.Semi: { flag = false; continue; } case TokenKind.AndAnd: case TokenKind.OrOr: { this.SkipToken(); this.SkipNewlines(); this.ReportError(token.Extent, ParserStrings.InvalidEndOfLine, new object[] { token.Text }); if (this.PeekToken().Kind == TokenKind.EndOfInput) { flag = false; } continue; } case TokenKind.Pipe: { this.SkipToken(); this.SkipNewlines(); if (this.PeekToken().Kind == TokenKind.EndOfInput) { flag = false; this.ReportIncompleteInput(After(token), ParserStrings.EmptyPipeElement, new object[0]); } continue; } } this.ReportError(token.Extent, ParserStrings.UnexpectedToken, new object[] { token.Text }); flag = false; } if (source.Count == 0) { return null; } return new PipelineAst(ExtentOf(first, source[source.Count - 1]), source); }
internal Ast CommandRule(bool forDynamicKeyword) { //G command: //G command-name command-elements:opt //G command-invocation-operator command-module:opt command-name-expr command-elements:opt //G command-invocation-operator: one of //G '&' '.' //G command-module: //G primary-expression //G command-name: //G generic-token //G generic-token-with-subexpr //G generic-token-with-subexpr: No whitespace is allowed between ) and command-name. //G generic-token-with-subexpr-start statement-list:opt ) command-name //G command-name-expr: //G command-name //G primary-expression //G command-elements: //G command-element //G command-elements command-element //G command-element: //G command-parameter //G command-argument //G redirection //G command-argument: //G command-name-expr Token firstToken; bool dotSource, ampersand; bool sawDashDash = false; bool foundVerbatimArgument = false; RedirectionAst[] redirections = null; IScriptExtent endExtent; var elements = new List<CommandElementAst>(); var oldTokenizerMode = _tokenizer.Mode; try { SetTokenizerMode(TokenizerMode.Command); Token token = NextToken(); firstToken = token; endExtent = token.Extent; dotSource = false; ampersand = false; CommandArgumentContext context; if (token.Kind == TokenKind.Dot) { dotSource = true; token = NextToken(); context = CommandArgumentContext.CommandNameAfterInvocationOperator; } else if (token.Kind == TokenKind.Ampersand) { ampersand = true; token = NextToken(); context = CommandArgumentContext.CommandNameAfterInvocationOperator; } else { context = CommandArgumentContext.CommandName; } bool scanning = true; while (scanning) { switch (token.Kind) { case TokenKind.Pipe: case TokenKind.RCurly: case TokenKind.RParen: case TokenKind.EndOfInput: case TokenKind.NewLine: case TokenKind.Semi: case TokenKind.AndAnd: case TokenKind.OrOr: UngetToken(token); scanning = false; continue; case TokenKind.Ampersand: // ErrorRecovery: just ignore the token. endExtent = token.Extent; ReportError(token.Extent, () => ParserStrings.AmpersandNotAllowed); break; case TokenKind.MinusMinus: endExtent = token.Extent; // Add the first -- as a parameter, which is then ignored when constructing the command processor unless it's a native // command. All subsequent -- are added as arguments. elements.Add(sawDashDash ? (CommandElementAst)new StringConstantExpressionAst(token.Extent, token.Text, StringConstantType.BareWord) : new CommandParameterAst(token.Extent, "-", null, token.Extent)); sawDashDash = true; break; case TokenKind.Comma: endExtent = token.Extent; ReportError(token.Extent, () => ParserStrings.MissingArgument); SkipNewlines(); break; case TokenKind.Parameter: if ((context & CommandArgumentContext.CommandName) != 0 || sawDashDash) { endExtent = token.Extent; token.TokenFlags |= TokenFlags.CommandName; var commandName = new StringConstantExpressionAst(token.Extent, token.Text, StringConstantType.BareWord); elements.Add(commandName); break; } var parameterToken = (ParameterToken)token; ExpressionAst parameterArgs; IScriptExtent extent; // If the next token is a comma, don't grab it as part of the argument. The next time through this // loop will issue an error. if (parameterToken.UsedColon && PeekToken().Kind != TokenKind.Comma) { parameterArgs = GetCommandArgument(CommandArgumentContext.CommandArgument, NextToken()); if (parameterArgs == null) { extent = parameterToken.Extent; ReportError(After(extent), () => ParserStrings.ParameterRequiresArgument, parameterToken.Text); } else { extent = ExtentOf(token, parameterArgs); } } else { parameterArgs = null; extent = token.Extent; } endExtent = extent; var paramAst = new CommandParameterAst(extent, parameterToken.ParameterName, parameterArgs, token.Extent); elements.Add(paramAst); break; case TokenKind.Redirection: case TokenKind.RedirectInStd: if ((context & CommandArgumentContext.CommandName) == 0) { if (redirections == null) { redirections = new RedirectionAst[CommandBaseAst.MaxRedirections]; } RedirectionRule((RedirectionToken)token, redirections, ref endExtent); } else { // For backwards compatibility, we allow redirection operators as command names. // V2 did not allow: // & << // but V3 and on will because it falls out rather naturally here. endExtent = token.Extent; elements.Add(new StringConstantExpressionAst(token.Extent, token.Text, StringConstantType.BareWord)); } break; default: if (token.Kind == TokenKind.InlineScript && context == CommandArgumentContext.CommandName) { scanning = InlineScriptRule(token, elements); Diagnostics.Assert(elements.Count >= 1, "We should at least have the command name: inlinescript"); endExtent = elements.Last().Extent; if (!scanning) { continue; } } else { var ast = GetCommandArgument(context, token); // If this is the special verbatim argument syntax, look for the next element StringToken argumentToken = token as StringToken; if ((argumentToken != null) && String.Equals(argumentToken.Value, VERBATIM_ARGUMENT, StringComparison.OrdinalIgnoreCase)) { elements.Add(ast); endExtent = ast.Extent; var verbatimToken = GetVerbatimCommandArgumentToken(); if (verbatimToken != null) { foundVerbatimArgument = true; scanning = false; ast = new StringConstantExpressionAst(verbatimToken.Extent, verbatimToken.Value, StringConstantType.BareWord); elements.Add(ast); endExtent = ast.Extent; } break; } endExtent = ast.Extent; elements.Add(ast); } break; } if (!foundVerbatimArgument) { context = CommandArgumentContext.CommandArgument; token = NextToken(); } } } finally { SetTokenizerMode(oldTokenizerMode); } if (elements.Count == 0) { Diagnostics.Assert(!forDynamicKeyword, "DynamicKeyword should have command name at least"); if (dotSource || ampersand) { IScriptExtent extent = firstToken.Extent; ReportError(extent, () => ParserStrings.MissingExpression, firstToken.Text); } return null; } if (forDynamicKeyword) { // TODO: report error if any redirections return new DynamicKeywordStatementAst(ExtentOf(firstToken, endExtent), elements); } return new CommandAst(ExtentOf(firstToken, endExtent), elements, dotSource || ampersand ? firstToken.Kind : TokenKind.Unknown, redirections != null ? redirections.Where(r => r != null) : null); }
private RedirectionAst RedirectionRule(RedirectionToken redirectionToken, RedirectionAst[] redirections, ref IScriptExtent extent) { //G redirections: //G redirection //G redirections redirection //G redirection: //G merging-redirection-operator //G file-redirection-operator redirected-file-name //G redirected-file-name: //G command-argument //G primary-expression RedirectionAst result; var fileRedirectionToken = redirectionToken as FileRedirectionToken; if (fileRedirectionToken != null || (redirectionToken is InputRedirectionToken)) { // get location var filename = GetSingleCommandArgument(CommandArgumentContext.FileName); if (filename == null) { // ErrorRecovery: Just pretend we have a filename and continue parsing. ReportError(After(redirectionToken), () => ParserStrings.MissingFileSpecification); filename = new ErrorExpressionAst(redirectionToken.Extent); } if (fileRedirectionToken == null) { // Must be an input redirection ReportError(redirectionToken.Extent, () => ParserStrings.RedirectionNotSupported, redirectionToken.Text); extent = ExtentOf(redirectionToken, filename); return null; } result = new FileRedirectionAst(ExtentOf(fileRedirectionToken, filename), fileRedirectionToken.FromStream, filename, fileRedirectionToken.Append); } else { var mergingRedirectionToken = (MergingRedirectionToken)redirectionToken; RedirectionStream fromStream = mergingRedirectionToken.FromStream; RedirectionStream toStream = mergingRedirectionToken.ToStream; if (toStream != RedirectionStream.Output) { // Have we seen something like 1>&2 or 2>&3 // ErrorRecovery: This is just a semantic error, so no special recovery. ReportError(redirectionToken.Extent, () => ParserStrings.RedirectionNotSupported, mergingRedirectionToken.Text); toStream = RedirectionStream.Output; } else if (fromStream == toStream) { // Make sure 1>&1, 2>&2, etc. is an error. // ErrorRecovery: This is just a semantic error, so no special recovery. ReportError(redirectionToken.Extent, () => ParserStrings.RedirectionNotSupported, mergingRedirectionToken.Text); } result = new MergingRedirectionAst(mergingRedirectionToken.Extent, mergingRedirectionToken.FromStream, toStream); } if (redirections[(int)result.FromStream] == null) { redirections[(int)result.FromStream] = result; } else { string errorStream; switch (result.FromStream) { case RedirectionStream.All: errorStream = ParserStrings.AllStream; break; case RedirectionStream.Output: errorStream = ParserStrings.OutputStream; break; case RedirectionStream.Error: errorStream = ParserStrings.ErrorStream; break; case RedirectionStream.Warning: errorStream = ParserStrings.WarningStream; break; case RedirectionStream.Verbose: errorStream = ParserStrings.VerboseStream; break; case RedirectionStream.Debug: errorStream = ParserStrings.DebugStream; break; case RedirectionStream.Information: errorStream = ParserStrings.InformationStream; break; default: throw PSTraceSource.NewArgumentOutOfRangeException("result.FromStream", result.FromStream); } ReportError(result.Extent, () => ParserStrings.StreamAlreadyRedirected, errorStream); } extent = result.Extent; return result; }
private PipelineBaseAst PipelineRule() { //G pipeline: //G assignment-expression //G expression redirections:opt pipeline-tail:opt //G command pipeline-tail:opt //G //G assignment-expression: //G expression assignment-operator statement //G //G pipeline-tail: //G '|' new-lines:opt command //G '|' new-lines:opt command pipeline-tail var pipelineElements = new List<CommandBaseAst>(); IScriptExtent startExtent = null; Token pipeToken = null; bool scanning = true; while (scanning) { CommandBaseAst commandAst; Token assignToken = null; ExpressionAst expr; var oldTokenizerMode = _tokenizer.Mode; try { SetTokenizerMode(TokenizerMode.Expression); expr = ExpressionRule(); if (expr != null) { // We peek here because we are in expression mode, otherwise =0 will get scanned // as a single token. var token = PeekToken(); if (token.Kind.HasTrait(TokenFlags.AssignmentOperator)) { SkipToken(); assignToken = token; } } } finally { SetTokenizerMode(oldTokenizerMode); } if (expr != null) { if (pipelineElements.Count > 0) { // ErrorRecovery: this is a semantic error, so just keep parsing. ReportError(expr.Extent, () => ParserStrings.ExpressionsMustBeFirstInPipeline); } if (assignToken != null) { SkipNewlines(); StatementAst statement = StatementRule(); if (statement == null) { // ErrorRecovery: we are very likely at EOF because pretty much anything should result in some // pipeline, so just keep parsing. IScriptExtent errorExtent = After(assignToken); ReportIncompleteInput(errorExtent, () => ParserStrings.ExpectedValueExpression, assignToken.Kind.Text()); statement = new ErrorStatementAst(errorExtent); } return new AssignmentStatementAst(ExtentOf(expr, statement), expr, assignToken.Kind, statement, assignToken.Extent); } RedirectionAst[] redirections = null; var redirectionToken = PeekToken() as RedirectionToken; RedirectionAst lastRedirection = null; while (redirectionToken != null) { SkipToken(); if (redirections == null) { redirections = new RedirectionAst[CommandBaseAst.MaxRedirections]; } IScriptExtent unused = null; lastRedirection = RedirectionRule(redirectionToken, redirections, ref unused); redirectionToken = PeekToken() as RedirectionToken; } var exprExtent = lastRedirection != null ? ExtentOf(expr, lastRedirection) : expr.Extent; commandAst = new CommandExpressionAst(exprExtent, expr, redirections != null ? redirections.Where(r => r != null) : null); } else { commandAst = (CommandAst)CommandRule(forDynamicKeyword: false); } if (commandAst != null) { if (startExtent == null) { startExtent = commandAst.Extent; } pipelineElements.Add(commandAst); } else if (pipelineElements.Count > 0 || PeekToken().Kind == TokenKind.Pipe) { // ErrorRecovery: just fall through // If the first pipe element is null, the position points to the pipe (ideally it would // point before, but the pipe could be the first character), otherwise the empty element // is after the pipe character. IScriptExtent errorPosition = pipeToken != null ? After(pipeToken) : PeekToken().Extent; ReportIncompleteInput(errorPosition, () => ParserStrings.EmptyPipeElement); } pipeToken = PeekToken(); switch (pipeToken.Kind) { case TokenKind.Semi: case TokenKind.NewLine: case TokenKind.RParen: case TokenKind.RCurly: case TokenKind.EndOfInput: scanning = false; continue; case TokenKind.Pipe: SkipToken(); SkipNewlines(); if (PeekToken().Kind == TokenKind.EndOfInput) { scanning = false; ReportIncompleteInput(After(pipeToken), () => ParserStrings.EmptyPipeElement); } break; case TokenKind.AndAnd: case TokenKind.OrOr: // Parse in a manner similar to a pipe, but issue an error (for now, but should implement this for V3.) SkipToken(); SkipNewlines(); ReportError(pipeToken.Extent, () => ParserStrings.InvalidEndOfLine, pipeToken.Text); if (PeekToken().Kind == TokenKind.EndOfInput) { scanning = false; } break; default: // ErrorRecovery: don't eat the token, assume it belongs to something else. ReportError(pipeToken.Extent, () => ParserStrings.UnexpectedToken, pipeToken.Text); scanning = false; break; } } if (pipelineElements.Count == 0) { return null; } return new PipelineAst(ExtentOf(startExtent, pipelineElements[pipelineElements.Count - 1]), pipelineElements); }