public void Visit(JsLabeledStatement node) { if (node != null) { node.Index = NextOrderIndex; if (node.Statement != null) { node.Statement.Accept(this); } } }
public void Visit(JsLabeledStatement node) { // invalid! ignore IsValid = false; }
public void Visit(JsLabeledStatement node) { // starts with a label identifier, so we don't care }
public void Visit(JsLabeledStatement node) { // not applicable; terminate }
public void Visit(JsLabeledStatement node) { Debug.Fail("shouldn't get here"); }
private JsAstNode ParseStatement(bool fSourceElement, bool skipImportantComment = false) { JsAstNode statement = null; // if we want to skip important comments, now is a good time to clear anything we may // have picked up already. if (skipImportantComment) { m_importantComments.Clear(); } if (m_importantComments.Count > 0 && m_settings.PreserveImportantComments && m_settings.IsModificationAllowed(JsTreeModifications.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 JsImportantComment(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 EndOfStreamException(); // abort parsing, get back to the main parse routine case JsToken.Semicolon: // make an empty statement statement = new JsEmptyStatement(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 JsBlock(CurrentPositionContext(), this); else return statement; case JsToken.Break: statement = ParseBreakStatement(); if (null == statement) return new JsBlock(CurrentPositionContext(), this); else return statement; case JsToken.Return: statement = ParseReturnStatement(); if (null == statement) return new JsBlock(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 JsBlock(CurrentPositionContext(), this); else break; case JsToken.Try: return ParseTryStatement(); case JsToken.Function: // parse a function declaration JsFunctionObject function = ParseFunction(JsFunctionType.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: { JsConditionalCompilationOn ccOn = new JsConditionalCompilationOn(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: { JsConditionalCompilationElse elseStatement = new JsConditionalCompilationElse(m_currentToken.Clone(), this); GetNextToken(); return elseStatement; } case JsToken.ConditionalCompilationEnd: { JsConditionalCompilationEnd endStatement = new JsConditionalCompilationEnd(m_currentToken.Clone(), this); GetNextToken(); return endStatement; } default: m_noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet); bool exprError = false; try { bool bAssign; statement = ParseUnaryExpression(out bAssign, false); // look for labels if (statement is JsLookup && 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 JsBlock(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) { // ignore any important comments between the label and its statement // because important comments are treated like statements, and we want // to make sure the label is attached to the right REAL statement. statement = new JsLabeledStatement(statement.Context.Clone(), this) { Label = id, ColonContext = colonContext, NestCount = labelNestCount, Statement = ParseStatement(fSourceElement, true) }; } else { // end of the file! //just pass null for the labeled statement statement = new JsLabeledStatement(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 JsConstantWrapper; if (constantWrapper != null && constantWrapper.PrimitiveType == JsPrimitiveType.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 JsDirectivePrologue)) { statement = new JsDirectivePrologue(constantWrapper.Value.ToString(), constantWrapper.Context, this) { MayHaveIssues = constantWrapper.MayHaveIssues }; } } } var binaryOp = statement as JsBinaryOperator; 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 JsLookup; 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 JsAspNetBlockNode(statement.Context, this) { AspNetBlockText = lookup.Name }; } var aspNetBlock = statement as JsAspNetBlockNode; 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(JsLabeledStatement node) { if (node != null) { var symbol = StartSymbol(node); if (m_settings.LocalRenaming != JsLocalRenaming.KeepAll && m_settings.IsModificationAllowed(JsTreeModifications.LocalRenaming)) { // we're minifying the labels. // we want to output our label as per our nested level. // top-level is "a", next level is "b", etc. // we don't need to worry about collisions with variables. Output(JsCrunchEnumerator.CrunchedLabel(node.NestCount) ?? node.Label); } else { // not minifying -- just output our label Output(node.Label); } MarkSegment(node, null, node.Context); SetContextOutputPosition(node.Context); OutputPossibleLineBreak(':'); MarkSegment(node, null, node.ColonContext); if (node.Statement != null && !node.Statement.HideFromOutput) { m_startOfStatement = true; node.Statement.Accept(this); } EndSymbol(symbol); } }