Exemplo n.º 1
0
        private ScriptRawStatement ParseRawStatement()
        {
            ScriptRawStatement scriptStatement = Open <ScriptRawStatement>();

            // We keep span End here to update it with the raw span
            TextPosition spanEnd = Current.End;

            // If we have an escape, we can fetch the escape count
            if (Current.Type == TokenType.Escape)
            {
                NextToken(); // Skip escape
                if (Current.Type < TokenType.EscapeCount1 && Current.Type > TokenType.EscapeCount9)
                {
                    LogError(Current, string.Format(RS.ExpectEscapeCount, GetAsText(Current)));
                }
                else
                {
                    scriptStatement.EscapeCount = (Current.Type - TokenType.EscapeCount1) + 1;
                }
            }

            scriptStatement.Text = _lexer.Text;
            NextToken(); // Skip raw or escape count
            Close(scriptStatement);

            // Because the previous will update the ScriptStatement with the wrong Span End for escape (escapecount1+)
            // We make sure that we use the span end of the Raw token
            scriptStatement.Span.End = spanEnd;
            return(scriptStatement);
        }
Exemplo n.º 2
0
        public TemplateRewriterContext Write(ScriptNode node)
        {
            if (node != null)
            {
                bool pushedWhileLoop = false;
                if (node is ScriptLoopStatementBase)
                {
                    _isWhileLoop.Push(node is ScriptWhileStatement);
                    pushedWhileLoop = true;
                }
                try
                {
                    WriteBegin(node);
                    node.Write(this);
                    WriteEnd(node);
                }
                finally
                {
                    if (pushedWhileLoop)
                    {
                        _isWhileLoop.Pop();
                    }

                    if (!IsBlockOrPage(node))
                    {
                        _previousRawStatement = node as ScriptRawStatement;
                    }
                }
            }
            return(this);
        }
Exemplo n.º 3
0
        private bool TryParseStatement(ScriptStatement parent, out ScriptStatement statement, out bool hasEnd)
        {
            hasEnd = false;
            bool nextStatement = true;

            statement = null;

continueParsing:

            if (_hasFatalError)
            {
                return(false);
            }

            if (_pendingStatements.Count > 0)
            {
                statement = _pendingStatements.Dequeue();
                return(true);
            }

            switch (Current.Type)
            {
            case TokenType.Eof:
                // Early exit
                nextStatement = false;
                break;

            case TokenType.Raw:
            case TokenType.Escape:
                statement = ParseRawStatement();
                if (parent is ScriptCaseStatement)
                {
                    // In case we have a raw statement within directly a case
                    // we don't keep it
                    statement = null;
                    goto continueParsing;
                }
                break;

            case TokenType.CodeEnter:
            case TokenType.LiquidTagEnter:
                if (_inCodeSection)
                {
                    LogError(RS.UnexpectedTokenInCodeBlock);
                }

                _isLiquidTagSection = Current.Type == TokenType.LiquidTagEnter;
                _inCodeSection      = true;

                // If we have any pending trivias before processing this code enter and we want to keep trivia
                // we need to generate a RawStatement to store these trivias
                if (_isKeepTrivia && (_trivias.Count > 0 || Previous.Type == TokenType.CodeEnter))
                {
                    ScriptRawStatement rawStatement = Open <ScriptRawStatement>();
                    Close(rawStatement);
                    if (_trivias.Count > 0)
                    {
                        rawStatement.Trivias.After.AddRange(rawStatement.Trivias.Before);
                        rawStatement.Trivias.Before.Clear();
                        SourceSpan firstTriviaSpan = rawStatement.Trivias.After[0].Span;
                        SourceSpan lastTriviaSpan  = rawStatement.Trivias.After[rawStatement.Trivias.After.Count - 1].Span;
                        rawStatement.Span = new SourceSpan(firstTriviaSpan.FileName, firstTriviaSpan.Start, lastTriviaSpan.End);
                    }
                    else
                    {
                        // Else Add an empty trivia
                        rawStatement.AddTrivia(new ScriptTrivia(CurrentSpan, ScriptTriviaType.Empty, null), false);
                    }
                    statement = rawStatement;
                }

                NextToken();

                if (Current.Type == TokenType.CodeExit)
                {
                    ScriptNopStatement nopStatement = Open <ScriptNopStatement>();
                    Close(nopStatement);
                    if (statement == null)
                    {
                        statement = nopStatement;
                    }
                    else
                    {
                        _pendingStatements.Enqueue(nopStatement);
                    }
                }

                // If we have a ScriptRawStatement previously defined, we need to break out of the loop to record it
                if (statement == null)
                {
                    goto continueParsing;
                }

                break;

            case TokenType.FrontMatterMarker:
                if (_inFrontMatter)
                {
                    _inFrontMatter = false;
                    _inCodeSection = false;
                    // When we expect to parse only the front matter, don't try to tokenize the following text
                    // Keep the current token as the code exit of the front matter
                    if (CurrentParsingMode != ScriptMode.FrontMatterOnly)
                    {
                        NextToken();
                    }

                    if (CurrentParsingMode == ScriptMode.FrontMatterAndContent || CurrentParsingMode == ScriptMode.FrontMatterOnly)
                    {
                        // Once the FrontMatter has been parsed, we can switch to default parsing mode.

                        CurrentParsingMode = ScriptMode.Default;
                        nextStatement      = false;
                    }
                }
                else
                {
                    LogError(string.Format(RS.UnexpectedFrontMatterMarker, _lexer.Options.FrontMatterMarker));
                    NextToken();
                }
                break;

            case TokenType.CodeExit:
            case TokenType.LiquidTagExit:
                if (!_inCodeSection)
                {
                    LogError(RS.OrphanCodeBlockExitError);
                }
                else if (CurrentParsingMode == ScriptMode.ScriptOnly)
                {
                    LogError(RS.CodeBlockNotAllowedInScriptMode);
                }

                _isLiquidTagSection = false;
                _inCodeSection      = false;

                // We clear any trivia that might not have been takend by a node
                // so that they don't end up after this token
                if (_isKeepTrivia)
                {
                    _trivias.Clear();
                }

                NextToken();

                // If next token is directly a code enter or an eof but we want to keep trivia
                // and with have trivias
                // we need to generate a RawStatement to store these trivias
                if (_isKeepTrivia && (Current.Type == TokenType.CodeEnter || Current.Type == TokenType.Eof))
                {
                    ScriptRawStatement rawStatement = Open <ScriptRawStatement>();
                    Close(rawStatement);
                    if (_trivias.Count > 0)
                    {
                        SourceSpan firstTriviaSpan = rawStatement.Trivias.Before[0].Span;
                        SourceSpan lastTriviaSpan  = rawStatement.Trivias.Before[rawStatement.Trivias.Before.Count - 1].Span;
                        rawStatement.Span = new SourceSpan(firstTriviaSpan.FileName, firstTriviaSpan.Start, lastTriviaSpan.End);
                    }
                    else
                    {
                        // Else Add an empty trivia
                        rawStatement.AddTrivia(new ScriptTrivia(CurrentSpan, ScriptTriviaType.Empty, null), false);
                    }
                    statement = rawStatement;
                }
                else
                {
                    goto continueParsing;
                }
                break;

            default:
                if (_inCodeSection)
                {
                    switch (Current.Type)
                    {
                    case TokenType.NewLine:
                    case TokenType.SemiColon:
                        PushTokenToTrivia();
                        NextToken();
                        goto continueParsing;

                    case TokenType.Identifier:
                    case TokenType.IdentifierSpecial:
                        string identifier = GetAsText(Current);
                        if (_isLiquid)
                        {
                            ParseLiquidStatement(identifier, parent, ref statement, ref hasEnd, ref nextStatement);
                        }
                        else
                        {
                            ParseTextScriptStatement(identifier, parent, ref statement, ref hasEnd, ref nextStatement);
                        }
                        break;

                    default:
                        if (StartAsExpression())
                        {
                            statement = ParseExpressionStatement();
                        }
                        else
                        {
                            nextStatement = false;
                            LogError(string.Format(RS.UnexpectedToken, Current.Type));
                        }
                        break;
                    }
                }
                else
                {
                    nextStatement = false;
                    LogError(string.Format(RS.UnexpectedTokenOutsideCodeBlock, Current.Type));
                    // LOG an ERROR. Don't expect any other tokens outside a code section
                }
                break;
            }

            return(nextStatement);
        }