Example #1
0
 public virtual void Visit(JsLexicalDeclaration node)
 {
     if (node != null)
     {
         foreach (var childNode in node.Children)
         {
             childNode.Accept(this);
         }
     }
 }
 public void Visit(JsLexicalDeclaration node)
 {
     // invalid! ignore
     IsValid = false;
 }
 public virtual void Visit(JsLexicalDeclaration node)
 {
     if (node != null)
     {
         foreach (var childNode in node.Children)
         {
             childNode.Accept(this);
         }
     }
 }
 public void Visit(JsLexicalDeclaration node)
 {
     if (node != null)
     {
         // lexical declarations get an order index
         node.Index = NextOrderIndex;
         for (var ndx = 0; ndx < node.Count; ++ndx)
         {
             var decl = node[ndx];
             if (decl != null)
             {
                 decl.Accept(this);
             }
         }
     }
 }
 public void Visit(JsLexicalDeclaration node)
 {
     Debug.Fail("shouldn't get here");
 }
Example #6
0
        //---------------------------------------------------------------------------------------
        // ParseVariableStatement
        //
        //  VariableStatement :
        //    'var' VariableDeclarationList
        //    or
        //    'const' VariableDeclarationList
        //    or
        //    'let' VariableDeclarationList
        //
        //  VariableDeclarationList :
        //    VariableDeclaration |
        //    VariableDeclaration ',' VariableDeclarationList
        //
        //  VariableDeclaration :
        //    Identifier Initializer
        //
        //  Initializer :
        //    <empty> |
        //    '=' AssignmentExpression
        //---------------------------------------------------------------------------------------
        private JsAstNode ParseVariableStatement()
        {
            // create the appropriate statement: var- or const-statement
            JsDeclaration varList;
            if (m_currentToken.Token == JsToken.Var)
            {
                varList = new JsVar(m_currentToken.Clone(), this);
            }
            else if (m_currentToken.Token == JsToken.Const || m_currentToken.Token == JsToken.Let)
            {
                if (m_currentToken.Token == JsToken.Const && m_settings.ConstStatementsMozilla)
                {
                    varList = new JsConstStatement(m_currentToken.Clone(), this);
                }
                else
                {
                    varList = new JsLexicalDeclaration(m_currentToken.Clone(), this)
                        {
                            StatementToken = m_currentToken.Token
                        };
                }
            }
            else
            {
                Debug.Fail("shouldn't get here");
                return null;
            }

            bool single = true;
            JsAstNode vdecl = null;
            JsAstNode identInit = null;

            for (; ; )
            {
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfLineToken);
                try
                {
                    identInit = ParseIdentifierInitializer(JsToken.None);
                }
                catch (RecoveryTokenException exc)
                {
                    // an exception is passing by, possibly bringing some info, save the info if any
                    if (exc._partiallyComputedNode != null)
                    {
                        if (!single)
                        {
                            varList.Append(exc._partiallyComputedNode);
                            varList.Context.UpdateWith(exc._partiallyComputedNode.Context);
                            exc._partiallyComputedNode = varList;
                        }
                    }
                    if (IndexOfToken(NoSkipTokenSet.s_EndOfLineToken, exc) == -1)
                        throw;
                    else
                    {
                        if (single)
                            identInit = exc._partiallyComputedNode;
                    }
                }
                finally
                {
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfLineToken);
                }

                if (identInit != null)
                {
                    vdecl = identInit;
                    varList.Append(vdecl);
                }

                if (m_currentToken.Token == JsToken.Comma)
                {
                    single = false;
                    vdecl.IfNotNull(d => d.TerminatingContext = m_currentToken.Clone());
                }
                else if (m_currentToken.Token == JsToken.Semicolon)
                {
                    varList.TerminatingContext = m_currentToken.Clone();
                    GetNextToken();
                    break;
                }
                else if (m_foundEndOfLine || m_currentToken.Token == JsToken.RightCurly || m_currentToken.Token == JsToken.EndOfFile)
                {
                    // semicolon insertion rules
                    // a right-curly or an end of line is something we don't WANT to throw a warning for.
                    // Just too common and doesn't really warrant a warning (in my opinion)
                    if (JsToken.RightCurly != m_currentToken.Token && JsToken.EndOfFile != m_currentToken.Token)
                    {
                        ReportError(JsError.SemicolonInsertion, varList.Context.IfNotNull(c => c.FlattenToEnd()), true);
                    }
                    break;
                }
                else
                {
                    ReportError(JsError.NoSemicolon, false);
                    break;
                }
            }

            if (vdecl != null)
            {
                varList.Context.UpdateWith(vdecl.Context);
            }
            return varList;
        }
Example #7
0
        private JsAstNode ParseForStatement()
        {
            m_blockType.Add(BlockType.Loop);
            JsAstNode forNode = null;
            try
            {
                JsContext forCtx = m_currentToken.Clone();
                GetNextToken();
                if (JsToken.LeftParenthesis != m_currentToken.Token)
                {
                    ReportError(JsError.NoLeftParenthesis);
                }

                GetNextToken();
                bool isForIn = false, recoveryInForIn = false;
                JsAstNode lhs = null, initializer = null, condOrColl = null, increment = null;
                JsContext operatorContext = null;
                JsContext separator1Context = null;
                JsContext separator2Context = null;

                try
                {
                    if (JsToken.Var == m_currentToken.Token
                        || JsToken.Let == m_currentToken.Token
                        || JsToken.Const == m_currentToken.Token)
                    {
                        isForIn = true;
                        JsDeclaration declaration;
                        if (m_currentToken.Token == JsToken.Var)
                        {
                            declaration = new JsVar(m_currentToken.Clone(), this);
                        }
                        else
                        {
                            declaration = new JsLexicalDeclaration(m_currentToken.Clone(), this)
                                {
                                    StatementToken = m_currentToken.Token
                                };
                        }

                        declaration.Append(ParseIdentifierInitializer(JsToken.In));

                        // a list of variable initializers is allowed only in a for(;;)
                        while (JsToken.Comma == m_currentToken.Token)
                        {
                            isForIn = false;
                            declaration.Append(ParseIdentifierInitializer(JsToken.In));
                            //initializer = new Comma(initializer.context.CombineWith(var.context), initializer, var);
                        }

                        initializer = declaration;

                        // if it could still be a for..in, now it's time to get the 'in'
                        // TODO: for ES6 might be 'of'
                        if (isForIn)
                        {
                            if (JsToken.In == m_currentToken.Token
                                || (m_currentToken.Token == JsToken.Identifier && string.CompareOrdinal(m_currentToken.Code, "of") == 0))
                            {
                                operatorContext = m_currentToken.Clone();
                                GetNextToken();
                                condOrColl = ParseExpression();
                            }
                            else
                            {
                                isForIn = false;
                            }
                        }
                    }
                    else
                    {
                        if (JsToken.Semicolon != m_currentToken.Token)
                        {
                            bool isLHS;
                            initializer = ParseUnaryExpression(out isLHS, false);
                            if (isLHS && (JsToken.In == m_currentToken.Token
                                || (m_currentToken.Token == JsToken.Identifier && string.CompareOrdinal(m_currentToken.Code, "of") == 0)))
                            {
                                isForIn = true;
                                operatorContext = m_currentToken.Clone();

                                lhs = initializer;
                                initializer = null;
                                GetNextToken();
                                m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                                try
                                {
                                    condOrColl = ParseExpression();
                                }
                                catch (RecoveryTokenException exc)
                                {
                                    if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1)
                                    {
                                        exc._partiallyComputedNode = null;
                                        throw;
                                    }
                                    else
                                    {
                                        if (exc._partiallyComputedNode == null)
                                            condOrColl = new JsConstantWrapper(true, JsPrimitiveType.Boolean, CurrentPositionContext(), this); // what could we put here?
                                        else
                                            condOrColl = exc._partiallyComputedNode;
                                    }
                                    if (exc._token == JsToken.RightParenthesis)
                                    {
                                        GetNextToken();
                                        recoveryInForIn = true;
                                    }
                                }
                                finally
                                {
                                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                                }
                            }
                            else
                            {
                                initializer = ParseExpression(initializer, false, isLHS, JsToken.In);
                            }
                        }
                    }
                }
                catch (RecoveryTokenException exc)
                {
                    // error is too early abort for
                    exc._partiallyComputedNode = null;
                    throw;
                }

                // at this point we know whether or not is a for..in
                if (isForIn)
                {
                    if (!recoveryInForIn)
                    {
                        if (JsToken.RightParenthesis != m_currentToken.Token)
                            ReportError(JsError.NoRightParenthesis);
                        forCtx.UpdateWith(m_currentToken);
                        GetNextToken();
                    }

                    JsAstNode body = null;
                    // if the statements aren't withing curly-braces, throw a possible error
                    if (JsToken.LeftCurly != m_currentToken.Token)
                    {
                        ReportError(JsError.StatementBlockExpected, CurrentPositionContext(), true);
                    }
                    try
                    {
                        // parse a Statement, not a SourceElement
                        // and ignore any important comments that spring up right here.
                        body = ParseStatement(false, true);
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (exc._partiallyComputedNode == null)
                            body = new JsBlock(CurrentPositionContext(), this);
                        else
                            body = exc._partiallyComputedNode;
                        exc._partiallyComputedNode = new JsForIn(forCtx, this)
                            {
                                Variable = (lhs != null ? lhs : initializer),
                                OperatorContext = operatorContext,
                                Collection = condOrColl,
                                Body = JsAstNode.ForceToBlock(body),
                            };
                        throw;
                    }

                    // for (a in b)
                    //      lhs = a, initializer = null
                    // for (var a in b)
                    //      lhs = null, initializer = var a
                    forNode = new JsForIn(forCtx, this)
                        {
                            Variable = (lhs != null ? lhs : initializer),
                            OperatorContext = operatorContext,
                            Collection = condOrColl,
                            Body = JsAstNode.ForceToBlock(body),
                        };
                }
                else
                {
                    m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                    try
                    {
                        if (JsToken.Semicolon == m_currentToken.Token)
                        {
                            separator1Context = m_currentToken.Clone();
                        }
                        else
                        {
                            ReportError(JsError.NoSemicolon);
                            if (JsToken.Colon == m_currentToken.Token)
                            {
                                m_noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                                try
                                {
                                    SkipTokensAndThrow();
                                }
                                catch (RecoveryTokenException)
                                {
                                    if (JsToken.Semicolon == m_currentToken.Token)
                                    {
                                        m_useCurrentForNext = false;
                                    }
                                    else
                                    {
                                        throw;
                                    }
                                }
                                finally
                                {
                                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                                }
                            }
                        }

                        GetNextToken();
                        if (JsToken.Semicolon != m_currentToken.Token)
                        {
                            condOrColl = ParseExpression();
                            if (JsToken.Semicolon != m_currentToken.Token)
                            {
                                ReportError(JsError.NoSemicolon);
                            }
                        }

                        separator2Context = m_currentToken.Clone();
                        GetNextToken();

                        if (JsToken.RightParenthesis != m_currentToken.Token)
                        {
                            increment = ParseExpression();
                        }

                        if (JsToken.RightParenthesis != m_currentToken.Token)
                        {
                            ReportError(JsError.NoRightParenthesis);
                        }

                        forCtx.UpdateWith(m_currentToken);
                        GetNextToken();
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1)
                        {
                            exc._partiallyComputedNode = null;
                            throw;
                        }
                        else
                        {
                            // discard any partial info, just genrate empty condition and increment and keep going
                            exc._partiallyComputedNode = null;
                            if (condOrColl == null)
                                condOrColl = new JsConstantWrapper(true, JsPrimitiveType.Boolean, CurrentPositionContext(), this);
                        }
                        if (exc._token == JsToken.RightParenthesis)
                        {
                            GetNextToken();
                        }
                    }
                    finally
                    {
                        m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                    }

                    // if this is an assignment, throw a warning in case the developer
                    // meant to use == instead of =
                    // but no warning if the condition is wrapped in parens.
                    var binOp = condOrColl as JsBinaryOperator;
                    if (binOp != null && binOp.OperatorToken == JsToken.Assign)
                    {
                        condOrColl.Context.HandleError(JsError.SuspectAssignment);
                    }

                    JsAstNode body = null;
                    // if the statements aren't withing curly-braces, throw a possible error
                    if (JsToken.LeftCurly != m_currentToken.Token)
                    {
                        ReportError(JsError.StatementBlockExpected, CurrentPositionContext(), true);
                    }
                    try
                    {
                        // parse a Statement, not a SourceElement
                        // and ignore any important comments that spring up right here.
                        body = ParseStatement(false, true);
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (exc._partiallyComputedNode == null)
                            body = new JsBlock(CurrentPositionContext(), this);
                        else
                            body = exc._partiallyComputedNode;
                        exc._partiallyComputedNode = new JsForNode(forCtx, this)
                            {
                                Initializer = initializer,
                                Separator1Context = separator1Context,
                                Condition = condOrColl,
                                Separator2Context = separator2Context,
                                Incrementer = increment,
                                Body = JsAstNode.ForceToBlock(body)
                            };
                        throw;
                    }
                    forNode = new JsForNode(forCtx, this)
                        {
                            Initializer = initializer,
                            Separator1Context = separator1Context,
                            Condition = condOrColl,
                            Separator2Context = separator2Context,
                            Incrementer = increment,
                            Body = JsAstNode.ForceToBlock(body)
                        };
                }
            }
            finally
            {
                m_blockType.RemoveAt(m_blockType.Count - 1);
            }

            return forNode;
        }
 public void Visit(JsLexicalDeclaration node)
 {
     // not applicable; terminate
 }
        public void Visit(JsLexicalDeclaration node)
        {
            if (node != null)
            {
                var symbol = StartSymbol(node);

                // save the no-in state -- we'll reset before processing each initializer
                var isNoIn = m_noIn;

                Output(OperatorString(node.StatementToken));
                MarkSegment(node, null, node.Context);
                SetContextOutputPosition(node.Context);
                m_startOfStatement = false;
                Indent();
                var useNewLines = !(node.Parent is JsForNode);

                for (var ndx = 0; ndx < node.Count; ++ndx)
                {
                    var decl = node[ndx];
                    if (decl != null)
                    {
                        if (ndx > 0)
                        {
                            OutputPossibleLineBreak(',');
                            if (useNewLines)
                            {
                                NewLine();
                            }
                            else if (m_settings.OutputMode == MinifierOutputMode.MultipleLines)
                            {
                                OutputPossibleLineBreak(' ');
                            }
                        }

                        // be sure to set the no-in state to whatever it was when we entered
                        // this node, because each declaration might reset it as it's outputting
                        // its child nodes
                        m_noIn = isNoIn;
                        decl.Accept(this);
                    }
                }

                Unindent();
                EndSymbol(symbol);
            }
        }