예제 #1
0
파일: Parser.cs 프로젝트: nickchal/pash
        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);
    }
예제 #2
0
 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);
 }
예제 #3
0
파일: Parser.cs 프로젝트: nickchal/pash
 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;
 }
예제 #4
0
파일: Parser.cs 프로젝트: nickchal/pash
        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);
        }
예제 #5
0
파일: Parser.cs 프로젝트: dfinke/powershell
        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);
        }
예제 #6
0
파일: Parser.cs 프로젝트: dfinke/powershell
        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;
        }
예제 #7
0
파일: Parser.cs 프로젝트: dfinke/powershell
        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);
        }