private AstNode ParseUnaryExpression()

in AjaxMinDll/JavaScript/jsparser.cs [3489:3670]


        private AstNode ParseUnaryExpression(out bool isLeftHandSideExpr, bool isMinus)
        {
            isLeftHandSideExpr = false;
            bool dummy = false;
            Context exprCtx = null;
            AstNode expr = null;

        TryItAgain:
            AstNode ast = null;
            var opToken = m_currentToken.Token;
            switch (opToken)
            {
                case JSToken.RestSpread:
                    // technically, we don't want rest operators ANYWHERE. But we need to handle them
                    // here specifically for formal parameter lists for arrow functions. 
                    // TODO: we want to error if we aren't immediately preceeded by a comma operator,
                    // and if after parsing the next unary expression, we're aren't at a closing parenthesis.
                    ParsedVersion = ScriptVersion.EcmaScript6;
                    goto case JSToken.Void;

                case JSToken.Void:
                case JSToken.TypeOf:
                case JSToken.Plus:
                case JSToken.Minus:
                case JSToken.BitwiseNot:
                case JSToken.LogicalNot:
                case JSToken.Delete:
                case JSToken.Increment:
                case JSToken.Decrement:
                    // normal unary operators all follow the same pattern
                    exprCtx = m_currentToken.Clone();
                    GetNextToken();
                    expr = ParseUnaryExpression(out dummy, false);
                    ast = new UnaryOperator(exprCtx.CombineWith(expr.Context))
                        {
                            Operand = expr,
                            OperatorContext = exprCtx,
                            OperatorToken = opToken
                        };
                    break;

                case JSToken.ConditionalCommentStart:
                    // skip past the start to the next token
                    exprCtx = m_currentToken.Clone();
                    GetNextToken();
                    if (m_currentToken.Is(JSToken.ConditionalCommentEnd))
                    {
                        // empty conditional-compilation comment -- ignore
                        GetNextToken();
                        goto TryItAgain;
                    }
                    else if (m_currentToken.Is(JSToken.ConditionalCompilationOn))
                    {
                        // /*@cc_on -- check for @IDENT@*/ or !@*/
                        GetNextToken();
                        if (m_currentToken.Is(JSToken.ConditionalCompilationVariable))
                        {
                            // /*@cc_on@IDENT -- check for @*/
                            ast = new ConstantWrapperPP(m_currentToken.Clone())
                                {
                                    VarName = m_currentToken.Code,
                                    ForceComments = true
                                };

                            GetNextToken();

                            if (m_currentToken.Is(JSToken.ConditionalCommentEnd))
                            {
                                // skip the close and keep going
                                GetNextToken();
                            }
                            else
                            {
                                // too complicated
                                CCTooComplicated(null);
                                goto TryItAgain;
                            }
                        }
                        else if (m_currentToken.Is(JSToken.LogicalNot))
                        {
                            // /*@cc_on! -- check for @*/
                            var operatorContext = m_currentToken.Clone();
                            GetNextToken();
                            if (m_currentToken.Is(JSToken.ConditionalCommentEnd))
                            {
                                // we have /*@cc_on!@*/
                                GetNextToken();
                                expr = ParseUnaryExpression(out dummy, false);
                                exprCtx.UpdateWith(expr.Context);

                                var unary = new UnaryOperator(exprCtx)
                                    {
                                        Operand = expr,
                                        OperatorContext = operatorContext,
                                        OperatorToken = JSToken.LogicalNot
                                    };
                                unary.OperatorInConditionalCompilationComment = true;
                                unary.ConditionalCommentContainsOn = true;
                                ast = unary;
                            }
                            else
                            {
                                // too complicated
                                CCTooComplicated(null);
                                goto TryItAgain;
                            }
                        }
                        else
                        {
                            // too complicated
                            CCTooComplicated(null);
                            goto TryItAgain;
                        }
                    }
                    else if (m_currentToken.Is(JSToken.LogicalNot))
                    {
                        // /*@! -- check for @*/
                        var operatorContext = m_currentToken.Clone();
                        GetNextToken();
                        if (m_currentToken.Is(JSToken.ConditionalCommentEnd))
                        {
                            // we have /*@!@*/
                            GetNextToken();
                            expr = ParseUnaryExpression(out dummy, false);
                            exprCtx.UpdateWith(expr.Context);

                            var unary = new UnaryOperator(exprCtx)
                                {
                                    Operand = expr,
                                    OperatorContext = operatorContext,
                                    OperatorToken = JSToken.LogicalNot
                                };
                            unary.OperatorInConditionalCompilationComment = true;
                            ast = unary;
                        }
                        else
                        {
                            // too complicated
                            CCTooComplicated(null);
                            goto TryItAgain;
                        }
                    }
                    else if (m_currentToken.Is(JSToken.ConditionalCompilationVariable))
                    {
                        // @IDENT -- check for @*/
                        ast = new ConstantWrapperPP(m_currentToken.Clone())
                            {
                                VarName = m_currentToken.Code,
                                ForceComments = true
                            };
                        GetNextToken();

                        if (m_currentToken.Is(JSToken.ConditionalCommentEnd))
                        {
                            // skip the close and keep going
                            GetNextToken();
                        }
                        else
                        {
                            // too complicated
                            CCTooComplicated(null);
                            goto TryItAgain;
                        }
                    }
                    else
                    {
                        // we ONLY support /*@id@*/ or /*@cc_on@id@*/ or /*@!@*/ or /*@cc_on!@*/ in expressions right now. 
                        // throw an error, skip to the end of the comment, then ignore it and start
                        // looking for the next token.
                        CCTooComplicated(null);
                        goto TryItAgain;
                    }
                    break;

                default:
                    ast = ParseLeftHandSideExpression(isMinus);
                    ast = ParsePostfixExpression(ast, out isLeftHandSideExpr);
                    break;
            }

            return ast;
        }