public void Visit(ImportantComment node)
 {
     // invalid! ignore
     IsValid = false;
 }
 public void Visit(ImportantComment node)
 {
     // nothing to do
 }
Example #3
0
        private AstNode ParseStatement(bool fSourceElement)
        {
            AstNode statement = null;
            if (m_importantComments.Count > 0 
                && m_settings.PreserveImportantComments
                && m_settings.IsModificationAllowed(TreeModifications.PreserveImportantComments))
            {
                // we have at least one important comment before the upcoming statement.
                // pop the first important comment off the queue, return that node instead.
                // don't advance the token -- we'll probably be coming back again for the next one (if any)
                statement = new ImportantComment(m_importantComments[0], this);
                m_importantComments.RemoveAt(0);
            }
            else
            {
                String id = null;
                var isNewModule = m_newModule;

                switch (m_currentToken.Token)
                {
                    case JSToken.EndOfFile:
                        EOFError(JSError.ErrorEndOfFile);
                        throw new EndOfFileException(); // abort parsing, get back to the main parse routine
                    case JSToken.Semicolon:
                        // make an empty statement
                        statement = new EmptyStatement(m_currentToken.Clone(), this);
                        GetNextToken();
                        return statement;
                    case JSToken.RightCurly:
                        ReportError(JSError.SyntaxError);
                        SkipTokensAndThrow();
                        break;
                    case JSToken.LeftCurly:
                        return ParseBlock();
                    case JSToken.Debugger:
                        return ParseDebuggerStatement();
                    case JSToken.Var:
                    case JSToken.Const:
                    case JSToken.Let:
                        return ParseVariableStatement();
                    case JSToken.If:
                        return ParseIfStatement();
                    case JSToken.For:
                        return ParseForStatement();
                    case JSToken.Do:
                        return ParseDoStatement();
                    case JSToken.While:
                        return ParseWhileStatement();
                    case JSToken.Continue:
                        statement = ParseContinueStatement();
                        if (null == statement)
                            return new Block(CurrentPositionContext(), this);
                        else
                            return statement;
                    case JSToken.Break:
                        statement = ParseBreakStatement();
                        if (null == statement)
                            return new Block(CurrentPositionContext(), this);
                        else
                            return statement;
                    case JSToken.Return:
                        statement = ParseReturnStatement();
                        if (null == statement)
                            return new Block(CurrentPositionContext(), this);
                        else
                            return statement;
                    case JSToken.With:
                        return ParseWithStatement();
                    case JSToken.Switch:
                        return ParseSwitchStatement();
                    case JSToken.Throw:
                        statement = ParseThrowStatement();
                        if (statement == null)
                            return new Block(CurrentPositionContext(), this);
                        else
                            break;
                    case JSToken.Try:
                        return ParseTryStatement();
                    case JSToken.Function:
                        // parse a function declaration
                        FunctionObject function = ParseFunction(FunctionType.Declaration, m_currentToken.Clone());
                        function.IsSourceElement = fSourceElement;
                        return function;
                    case JSToken.Else:
                        ReportError(JSError.InvalidElse);
                        SkipTokensAndThrow();
                        break;
                    case JSToken.ConditionalCommentStart:
                        return ParseStatementLevelConditionalComment(fSourceElement);
                    case JSToken.ConditionalCompilationOn:
                        {
                            ConditionalCompilationOn ccOn = new ConditionalCompilationOn(m_currentToken.Clone(), this);
                            GetNextToken();
                            return ccOn;
                        }
                    case JSToken.ConditionalCompilationSet:
                        return ParseConditionalCompilationSet();
                    case JSToken.ConditionalCompilationIf:
                        return ParseConditionalCompilationIf(false);
                    case JSToken.ConditionalCompilationElseIf:
                        return ParseConditionalCompilationIf(true);
                    case JSToken.ConditionalCompilationElse:
                        {
                            ConditionalCompilationElse elseStatement = new ConditionalCompilationElse(m_currentToken.Clone(), this);
                            GetNextToken();
                            return elseStatement;
                        }
                    case JSToken.ConditionalCompilationEnd:
                        {
                            ConditionalCompilationEnd endStatement = new ConditionalCompilationEnd(m_currentToken.Clone(), this);
                            GetNextToken();
                            return endStatement;
                        }

                    default:
                        m_noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet);
                        bool exprError = false;
                        try
                        {
                            bool bAssign;
                            // if this statement starts with a function within parens, we want to know now
                            bool parenFunction = (m_currentToken.Token == JSToken.LeftParenthesis && PeekToken() == JSToken.Function);
                            statement = ParseUnaryExpression(out bAssign, false);
                            if (statement != null && parenFunction)
                            {
                                FunctionObject functionObject = statement.LeftHandSide as FunctionObject;
                                if (functionObject != null)
                                {
                                    functionObject.LeftHandFunctionExpression = true;
                                }
                            }

                            // look for labels
                            if (statement is Lookup && JSToken.Colon == m_currentToken.Token)
                            {
                                // can be a label
                                id = statement.ToString();
                                if (m_labelTable.ContainsKey(id))
                                {
                                    // there is already a label with that name. Ignore the current label
                                    ReportError(JSError.BadLabel, statement.Context.Clone(), true);
                                    id = null;
                                    GetNextToken(); // skip over ':'
                                    return new Block(CurrentPositionContext(), this);
                                }
                                else
                                {
                                    var colonContext = m_currentToken.Clone();
                                    GetNextToken();
                                    int labelNestCount = m_labelTable.Count + 1;
                                    m_labelTable.Add(id, new LabelInfo(m_blockType.Count, labelNestCount));
                                    if (JSToken.EndOfFile != m_currentToken.Token)
                                    {
                                        statement = new LabeledStatement(statement.Context.Clone(), this)
                                            {
                                                Label = id,
                                                ColonContext = colonContext,
                                                NestCount = labelNestCount,
                                                Statement = ParseStatement(fSourceElement)
                                            };
                                    }
                                    else
                                    {
                                        // end of the file!
                                        //just pass null for the labeled statement
                                        statement = new LabeledStatement(statement.Context.Clone(), this)
                                            {
                                                Label = id,
                                                ColonContext = colonContext,
                                                NestCount = labelNestCount
                                            };
                                    }
                                    m_labelTable.Remove(id);
                                    return statement;
                                }
                            }
                            statement = ParseExpression(statement, false, bAssign, JSToken.None);

                            // if we just started a new module and this statement happens to be an expression statement...
                            if (isNewModule && statement.IsExpression)
                            {
                                // see if it's a constant wrapper
                                var constantWrapper = statement as ConstantWrapper;
                                if (constantWrapper != null && constantWrapper.PrimitiveType == PrimitiveType.String)
                                {
                                    // we found a string constant expression statement right after the start of a new
                                    // module. Let's make it a DirectivePrologue if it isn't already
                                    if (!(statement is DirectivePrologue))
                                    {
                                        statement = new DirectivePrologue(constantWrapper.Value.ToString(), constantWrapper.Context, this)
                                            {
                                                MayHaveIssues = constantWrapper.MayHaveIssues
                                            };
                                    }
                                }
                            }

                            var binaryOp = statement as BinaryOperator;
                            if (binaryOp != null
                                && (binaryOp.OperatorToken == JSToken.Equal || binaryOp.OperatorToken == JSToken.StrictEqual))
                            {
                                // an expression statement with equality operator? Doesn't really do anything.
                                // Did the developer intend this to be an assignment operator instead? Low-pri warning.
                                binaryOp.OperatorContext.IfNotNull(c => c.HandleError(JSError.SuspectEquality, false));
                            }

                            var lookup = statement as Lookup;
                            if (lookup != null
                                && lookup.Name.StartsWith("<%=", StringComparison.Ordinal) && lookup.Name.EndsWith("%>", StringComparison.Ordinal))
                            {
                                // single lookup, but it's actually one or more ASP.NET blocks.
                                // convert back to an asp.net block node
                                statement = new AspNetBlockNode(statement.Context, this)
                                {
                                    AspNetBlockText = lookup.Name
                                };
                            }

                            var aspNetBlock = statement as AspNetBlockNode;
                            if (aspNetBlock != null && JSToken.Semicolon == m_currentToken.Token)
                            {
                                aspNetBlock.IsTerminatedByExplicitSemicolon = true;
                                statement.IfNotNull(s => s.TerminatingContext = m_currentToken.Clone());
                                GetNextToken();
                            }

                            // we just parsed an expression statement. Now see if we have an appropriate
                            // semicolon to terminate it.
                            if (JSToken.Semicolon == m_currentToken.Token)
                            {
                                statement.IfNotNull(s => s.TerminatingContext = m_currentToken.Clone());
                                GetNextToken();
                            }
                            else if (m_foundEndOfLine || JSToken.RightCurly == m_currentToken.Token || JSToken.EndOfFile == m_currentToken.Token)
                            {
                                // semicolon insertion rules
                                // (if there was no statement parsed, then don't fire a warning)
                                // 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 (statement != null
                                    && JSToken.RightCurly != m_currentToken.Token && JSToken.EndOfFile != m_currentToken.Token)
                                {
                                    ReportError(JSError.SemicolonInsertion, statement.Context.IfNotNull(c => c.FlattenToEnd()), true);
                                }
                            }
                            else
                            {
                                ReportError(JSError.NoSemicolon, true);
                            }
                        }
                        catch (RecoveryTokenException exc)
                        {
                            if (exc._partiallyComputedNode != null)
                                statement = exc._partiallyComputedNode;

                            if (statement == null)
                            {
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet);
                                exprError = true;
                                SkipTokensAndThrow();
                            }

                            if (IndexOfToken(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet, exc) == -1)
                            {
                                exc._partiallyComputedNode = statement;
                                throw;
                            }
                        }
                        finally
                        {
                            if (!exprError)
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet);
                        }
                        break;
                }
            }

            return statement;
        }
 public void Visit(ImportantComment node)
 {
     // don't recurse
 }
 public void Visit(ImportantComment node)
 {
     // not applicable; terminate
 }