protected override void OnScriptLiteral(ScriptLiteral literal)
 {
     if (FlagNotSet(Flag.RemoveScriptTags))
     {
         base.OnScriptLiteral(literal);
     }
 }
示例#2
0
        private ScriptLiteral ParseImplicitString()
        {
            ScriptLiteral literal = Open <ScriptLiteral>();

            literal.Value = GetAsText(Current);
            Close(literal);
            NextToken();
            return(literal);
        }
示例#3
0
        private ScriptLiteral ParseVerbatimString()
        {
            ScriptLiteral literal = Open <ScriptLiteral>();
            string        text    = _lexer.Text;

            literal.StringQuoteType = ScriptLiteralStringQuoteType.Verbatim;

            StringBuilder builder = null;

            // startOffset start at the first character (`a` in the string `abc`)
            int startOffset = Current.Start.Offset + 1;
            // endOffset is at the last character (`c` in the string `abc`)
            int endOffset = Current.End.Offset - 1;

            int offset = startOffset;

            while (true)
            {
                // Go to the next escape (the lexer verified that there was a following `)
                int nextOffset = text.IndexOf("`", offset, endOffset - offset + 1, StringComparison.OrdinalIgnoreCase);
                if (nextOffset < 0)
                {
                    break;
                }

                if (builder == null)
                {
                    builder = new StringBuilder(endOffset - startOffset + 1);
                }


                builder.Append(text.Substring(offset, nextOffset - offset + 1));

                // Skip the escape ``
                offset = nextOffset + 2;
            }
            if (builder != null)
            {
                int count = endOffset - offset + 1;
                if (count > 0)
                {
                    builder.Append(text.Substring(offset, count));
                }

                literal.Value = builder.ToString();
            }
            else
            {
                literal.Value = text.Substring(offset, endOffset - offset + 1);
            }

            NextToken();
            return(Close(literal));
        }
示例#4
0
        protected override void OnScriptLiteral(ScriptLiteral literal)
        {
            if (literal == null || _scriptDepth > 0)
            {
                return;
            }

            literal.LiteralText = ReplaceValue(literal.LiteralText);
            Emit(literal.ToString());
            base.OnScriptLiteral(literal);
        }
示例#5
0
        private ScriptLiteral ParseFloat()
        {
            ScriptLiteral literal = Open <ScriptLiteral>();

            string text = GetAsText(Current);
            double floatResult;

            if (double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out floatResult))
            {
                literal.Value = floatResult;
            }
            else
            {
                LogError(string.Format(RS.ParseLiteralFailed, text, "double"));
            }

            NextToken(); // Skip the float
            return(Close(literal));
        }
示例#6
0
        private ScriptLiteral ParseInteger()
        {
            ScriptLiteral literal = Open <ScriptLiteral>();

            string text = GetAsText(Current);
            long   result;

            if (!long.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
            {
                LogError(string.Format(RS.ParseLiteralFailed, text, "integer"));
            }

            if (result >= int.MinValue && result <= int.MaxValue)
            {
                literal.Value = (int)result;
            }
            else
            {
                literal.Value = result;
            }

            NextToken(); // Skip the literal
            return(Close(literal));
        }
示例#7
0
        private ScriptExpression ParseVariable()
        {
            var currentToken = Current;
            var currentSpan  = CurrentSpan;
            var endSpan      = currentSpan;
            var text         = GetAsText(currentToken);

            // Return ScriptLiteral for null, true, false
            // Return ScriptAnonymousFunction
            switch (text)
            {
            case "null":
                var nullValue = Open <ScriptLiteral>();
                NextToken();
                return(Close(nullValue));

            case "true":
                var trueValue = Open <ScriptLiteral>();
                trueValue.Value = true;
                NextToken();
                return(Close(trueValue));

            case "false":
                var falseValue = Open <ScriptLiteral>();
                falseValue.Value = false;
                NextToken();
                return(Close(falseValue));

            case "do":
                var functionExp = Open <ScriptAnonymousFunction>();
                functionExp.Function = ParseFunctionStatement(true);
                var func = Close(functionExp);
                return(func);

            case "this":
                if (!_isLiquid)
                {
                    var thisExp = Open <ScriptThisExpression>();
                    ExpectAndParseKeywordTo(thisExp.ThisKeyword);
                    return(Close(thisExp));
                }
                break;
            }

            // Keeps trivia before this token
            List <ScriptTrivia> triviasBefore = null;

            if (_isKeepTrivia && _trivias.Count > 0)
            {
                triviasBefore = new List <ScriptTrivia>();
                triviasBefore.AddRange(_trivias);
                _trivias.Clear();
            }

            NextToken();
            var scope = ScriptVariableScope.Global;

            if (text.StartsWith("$"))
            {
                scope = ScriptVariableScope.Local;
                text  = text.Substring(1);

                // Convert $0, $1... $n variable into $[0] $[1]...$[n] variables
                int index;
                if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
                {
                    var target = new ScriptVariableLocal(ScriptVariable.Arguments.BaseName)
                    {
                        Span = currentSpan
                    };
                    var indexLiteral = new ScriptLiteral()
                    {
                        Span = currentSpan, Value = index
                    };

                    var indexerExpression = new ScriptIndexerExpression
                    {
                        Span   = currentSpan,
                        Target = target,
                        Index  = indexLiteral
                    };

                    if (_isKeepTrivia)
                    {
                        if (triviasBefore != null)
                        {
                            target.AddTrivias(triviasBefore, true);
                        }

                        // Special case, we add the trivias to the index as the [] brackets
                        // won't be output-ed
                        FlushTrivias(indexLiteral, false);
                        _lastTerminalWithTrivias = indexLiteral;
                    }

                    return(indexerExpression);
                }
            }
            else if (text == "for" || text == "while" || text == "tablerow" || (_isLiquid && (text == "forloop" || text == "tablerowloop")))
            {
                if (Current.Type == TokenType.Dot)
                {
                    scope = ScriptVariableScope.Loop;
                    var token = PeekToken();
                    if (token.Type == TokenType.Identifier)
                    {
                        //endSpan = GetSpanForToken(token);
                        var loopVariableText = GetAsText(token);
                        if (_isLiquid)
                        {
                            switch (loopVariableText)
                            {
                            case "first":
                            case "last":
                            case "index0":
                            case "rindex0":
                            case "index":
                            case "rindex":
                            case "length":
                                break;

                            case "col":
                                if (text != "tablerowloop")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, $"The loop variable <{text}.col> is invalid");
                                }
                                break;

                            default:
                                LogError(currentToken, $"The liquid loop variable <{text}.{loopVariableText}> is not supported");
                                break;
                            }

                            if (text == "forloop")
                            {
                                text = "for";
                            }
                            else if (text == "tablerowloop")
                            {
                                text = "tablerow";
                            }
                        }
                        else
                        {
                            switch (loopVariableText)
                            {
                            // supported by both for and while
                            case "first":
                            case "even":
                            case "odd":
                            case "index":
                                break;

                            case "last":
                            case "changed":
                            case "length":
                            case "rindex":
                                if (text == "while")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, $"The loop variable <while.{loopVariableText}> is invalid");
                                }
                                break;

                            case "col":
                                if (text != "tablerow")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, $"The loop variable <{text}.col> is invalid");
                                }
                                break;

                            default:
                                // unit test: 108-variable-loop-error1.txt
                                LogError(currentToken, $"The loop variable <{text}.{loopVariableText}> is not supported");
                                break;
                            }
                        }
                    }
                    else
                    {
                        LogError(currentToken, $"Invalid token `{GetAsText(Current)}`. The loop variable <{text}> dot must be followed by an identifier");
                    }
                }
            }
            else if (_isLiquid && text == "continue")
            {
                scope = ScriptVariableScope.Local;
            }

            var result = ScriptVariable.Create(text, scope);

            result.Span = new SourceSpan
            {
                FileName = currentSpan.FileName,
                Start    = currentSpan.Start,
                End      = endSpan.End
            };

            // A liquid variable can have `-` in its identifier
            // If this is the case, we need to translate it to `this["this"]` instead
            if (_isLiquid && text.IndexOf('-') >= 0)
            {
                var target = new ScriptThisExpression()
                {
                    Span = result.Span
                };
                var newExp = new ScriptIndexerExpression
                {
                    Target = target,
                    Index  = new ScriptLiteral(text)
                    {
                        Span = result.Span
                    },
                    Span = result.Span
                };

                // Flush any trivias after
                if (_isKeepTrivia)
                {
                    if (triviasBefore != null)
                    {
                        target.ThisKeyword.AddTrivias(triviasBefore, true);
                    }
                    FlushTrivias(newExp.CloseBracket, false);
                    _lastTerminalWithTrivias = newExp.CloseBracket;
                }

                // Return the expression
                return(newExp);
            }

            if (_isKeepTrivia)
            {
                // Flush any trivias after
                if (triviasBefore != null)
                {
                    result.AddTrivias(triviasBefore, true);
                }
                FlushTrivias(result, false);

                _lastTerminalWithTrivias = result;
            }

            return(result);
        }
示例#8
0
        private ScriptExpression ParseVariable()
        {
            Token      currentToken = Current;
            SourceSpan currentSpan  = CurrentSpan;
            SourceSpan endSpan      = currentSpan;
            string     text         = GetAsText(currentToken);

            // Return ScriptLiteral for null, true, false
            // Return ScriptAnonymousFunction
            switch (text)
            {
            case "null":
                ScriptLiteral nullValue = Open <ScriptLiteral>();
                NextToken();
                return(Close(nullValue));

            case "true":
                ScriptLiteral trueValue = Open <ScriptLiteral>();
                trueValue.Value = true;
                NextToken();
                return(Close(trueValue));

            case "false":
                ScriptLiteral falseValue = Open <ScriptLiteral>();
                falseValue.Value = false;
                NextToken();
                return(Close(falseValue));

            case "do":
                ScriptAnonymousFunction functionExp = Open <ScriptAnonymousFunction>();
                functionExp.Function = ParseFunctionStatement(true);
                ScriptAnonymousFunction func = Close(functionExp);
                return(func);

            case "this":
                if (!_isLiquid)
                {
                    ScriptThisExpression thisExp = Open <ScriptThisExpression>();
                    NextToken();
                    return(Close(thisExp));
                }
                break;
            }

            // Keeps trivia before this token
            List <ScriptTrivia> triviasBefore = null;

            if (_isKeepTrivia && _trivias.Count > 0)
            {
                triviasBefore = new List <ScriptTrivia>();
                triviasBefore.AddRange(_trivias);
                _trivias.Clear();
            }

            NextToken();
            ScriptVariableScope scope = ScriptVariableScope.Global;

            if (text.StartsWith("$"))
            {
                scope = ScriptVariableScope.Local;
                text  = text.Substring(1);

                // Convert $0, $1... $n variable into $[0] $[1]...$[n] variables
                int index;
                if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
                {
                    ScriptIndexerExpression indexerExpression = new ScriptIndexerExpression
                    {
                        Span = currentSpan,

                        Target = new ScriptVariableLocal(ScriptVariable.Arguments.Name)
                        {
                            Span = currentSpan
                        },

                        Index = new ScriptLiteral()
                        {
                            Span = currentSpan, Value = index
                        }
                    };

                    if (_isKeepTrivia)
                    {
                        if (triviasBefore != null)
                        {
                            indexerExpression.Target.AddTrivias(triviasBefore, true);
                        }

                        FlushTrivias(indexerExpression.Index, false);
                    }

                    return(indexerExpression);
                }
            }
            else if (text == "for" || text == "while" || text == "tablerow" || (_isLiquid && (text == "forloop" || text == "tablerowloop")))
            {
                if (Current.Type == TokenType.Dot)
                {
                    NextToken();
                    if (Current.Type == TokenType.Identifier)
                    {
                        endSpan = CurrentSpan;
                        string loopVariableText = GetAsText(Current);
                        NextToken();

                        scope = ScriptVariableScope.Loop;
                        if (_isLiquid)
                        {
                            switch (loopVariableText)
                            {
                            case "first":
                                text = ScriptVariable.LoopFirst.Name;
                                break;

                            case "last":
                                text = ScriptVariable.LoopLast.Name;
                                break;

                            case "index0":
                                text = ScriptVariable.LoopIndex.Name;
                                break;

                            case "rindex0":
                                text = ScriptVariable.LoopRIndex.Name;
                                break;

                            case "rindex":
                            case "index":
                                // Because forloop.index is 1 based index, we need to create a binary expression
                                // to support it here
                                bool isrindex = loopVariableText == "rindex";

                                ScriptNestedExpression nested = new ScriptNestedExpression()
                                {
                                    Expression = new ScriptBinaryExpression()
                                    {
                                        Operator = ScriptBinaryOperator.Add,
                                        Left     = new ScriptVariableLoop(isrindex ? ScriptVariable.LoopRIndex.Name : ScriptVariable.LoopIndex.Name)
                                        {
                                            Span = currentSpan
                                        },
                                        Right = new ScriptLiteral(1)
                                        {
                                            Span = currentSpan
                                        },
                                        Span = currentSpan
                                    },
                                    Span = currentSpan
                                };

                                if (_isKeepTrivia)
                                {
                                    if (triviasBefore != null)
                                    {
                                        nested.AddTrivias(triviasBefore, true);
                                    }

                                    FlushTrivias(nested, false);
                                }
                                return(nested);

                            case "length":
                                text = ScriptVariable.LoopLength.Name;
                                break;

                            case "col":
                                if (text != "tablerowloop")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, string.Format(RS.InvalidLoopVariable, text + ".col"));
                                }
                                text = ScriptVariable.TableRowCol.Name;
                                break;

                            default:
                                text = text + "." + loopVariableText;
                                LogError(currentToken, string.Format(RS.InvalidLiquidLoopVariable, text));
                                break;
                            }
                        }
                        else
                        {
                            switch (loopVariableText)
                            {
                            case "first":
                                text = ScriptVariable.LoopFirst.Name;
                                break;

                            case "last":
                                if (text == "while")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, string.Format(RS.InvalidLoopVariable, "while.last"));
                                }
                                text = ScriptVariable.LoopLast.Name;
                                break;

                            case "changed":
                                if (text == "while")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, string.Format(RS.InvalidLoopVariable, "while.changed"));
                                }
                                text = ScriptVariable.LoopChanged.Name;
                                break;

                            case "length":
                                if (text == "while")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, string.Format(RS.InvalidLoopVariable, "while.length"));
                                }
                                text = ScriptVariable.LoopLength.Name;
                                break;

                            case "even":
                                text = ScriptVariable.LoopEven.Name;
                                break;

                            case "odd":
                                text = ScriptVariable.LoopOdd.Name;
                                break;

                            case "index":
                                text = ScriptVariable.LoopIndex.Name;
                                break;

                            case "rindex":
                                if (text == "while")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, string.Format(RS.InvalidLoopVariable, "while.rindex"));
                                }
                                text = ScriptVariable.LoopRIndex.Name;
                                break;

                            case "col":
                                if (text != "tablerow")
                                {
                                    // unit test: 108-variable-loop-error2.txt
                                    LogError(currentToken, string.Format(RS.InvalidLoopVariable, text + ".col"));
                                }
                                text = ScriptVariable.TableRowCol.Name;
                                break;

                            default:
                                text = text + "." + loopVariableText;
                                // unit test: 108-variable-loop-error1.txt
                                LogError(currentToken, string.Format(RS.InvalidLoopVariable, text));
                                break;
                            }
                        }

                        // We no longer checks at parse time usage of loop variables, as they can be used in a wrap context
                        //if (!IsInLoop())
                        //{
                        //    LogError(currentToken, string.Format(RS.InvalidLoopVariableOutsideLoop, text));
                        //}
                    }
                    else
                    {
                        LogError(currentToken, string.Format(RS.LoopVariableDotRequireIdentifier, Current.Type, text));
                    }
                }
            }
            else if (_isLiquid && text == "continue")
            {
                scope = ScriptVariableScope.Local;
            }

            ScriptVariable result = ScriptVariable.Create(text, scope);

            result.Span = new SourceSpan
            {
                FileName = currentSpan.FileName,
                Start    = currentSpan.Start,
                End      = endSpan.End
            };

            // A liquid variable can have `-` in its identifier
            // If this is the case, we need to translate it to `this["this"]` instead
            if (_isLiquid && text.IndexOf('-') >= 0)
            {
                ScriptIndexerExpression newExp = new ScriptIndexerExpression
                {
                    Target = new ScriptThisExpression()
                    {
                        Span = result.Span
                    },
                    Index = new ScriptLiteral(text)
                    {
                        Span = result.Span
                    },
                    Span = result.Span
                };

                // Flush any trivias after
                if (_isKeepTrivia)
                {
                    if (triviasBefore != null)
                    {
                        newExp.Target.AddTrivias(triviasBefore, true);
                    }

                    FlushTrivias(newExp, false);
                }
                // Return the expression
                return(newExp);
            }

            if (_isKeepTrivia)
            {
                // Flush any trivias after
                if (triviasBefore != null)
                {
                    result.AddTrivias(triviasBefore, true);
                }


                FlushTrivias(result, false);
            }
            return(result);
        }
示例#9
0
        private ScriptLiteral ParseString()
        {
            ScriptLiteral literal = Open <ScriptLiteral>();
            string        text    = _lexer.Text;
            StringBuilder builder = new StringBuilder(Current.End.Offset - Current.Start.Offset - 1);

            literal.StringQuoteType = _lexer.Text[Current.Start.Offset] == '\''
                ? ScriptLiteralStringQuoteType.SimpleQuote
                : ScriptLiteralStringQuoteType.DoubleQuote;

            int end = Current.End.Offset;

            for (int i = Current.Start.Offset + 1; i < end; i++)
            {
                char c = text[i];
                // Handle escape characters
                if (text[i] == SpecialChar.EscapeChar)
                {
                    i++;
                    switch (text[i])
                    {
                    case '0':
                        builder.Append(SpecialChar.Null);
                        break;

                    case SpecialChar.NewLine:
                        // line break right after an escape char - just ignore
                        break;

                    case SpecialChar.CarriageReturn:
                        // line break right after an escape char - just ignore
                        i++;     // skip next \n that was validated by the lexer
                        break;

                    case SpecialChar.SingleQuote:
                        builder.Append(SpecialChar.SingleQuote);
                        break;

                    case SpecialChar.DoubleQuote:
                        builder.Append(SpecialChar.DoubleQuote);
                        break;

                    case SpecialChar.EscapeChar:
                        builder.Append(SpecialChar.EscapeChar);
                        break;

                    case 'b':
                        builder.Append(SpecialChar.Backspace);
                        break;

                    case 'f':
                        builder.Append(SpecialChar.FormFeed);
                        break;

                    case 'n':
                        builder.Append(SpecialChar.NewLine);
                        break;

                    case 'r':
                        builder.Append(SpecialChar.CarriageReturn);
                        break;

                    case 't':
                        builder.Append(SpecialChar.Tab);
                        break;

                    case 'v':
                        builder.Append(SpecialChar.VerticalTab);
                        break;

                    case 'u':
                    {
                        // unicode value - u???? - where ???? in 0000 to ffff
                        i++;
                        int value = (text[i++].HexToInt() << 12) +
                                    (text[i++].HexToInt() << 8) +
                                    (text[i++].HexToInt() << 4) +
                                    text[i].HexToInt();

                        // Is it correct?
                        builder.Append(ConvertFromUtf32(value));
                        break;
                    }

                    case 'x':
                    {
                        // hex value - x?? - where ?? in 00 to ff

                        i++;
                        int value = (text[i++].HexToInt() << 4) +
                                    text[i++].HexToInt();

                        builder.Append((char)value);
                        break;
                    }

                    default:
                    {
                        // This should not happen as the lexer is supposed to prevent this
                        LogError(string.Format(RS.InvalidEscapeChar, text[i]));
                        break;
                    }
                    }
                }
                else
                {
                    builder.Append(c);
                }
            }
            literal.Value = builder.ToString();

            NextToken();
            return(Close(literal));
        }
示例#10
0
 protected override void OnScriptLiteral(ScriptLiteral literal)
 {
 }
        public void Parse()
        {
            SimpleHtmlParser parser = new SimpleHtmlParser(_html);

            OnDocumentBegin();
            while (true)
            {
                Element currentElement = parser.Next();

                BeginTag beginTag = currentElement as BeginTag;
                if (beginTag != null)
                {
                    OnBeginTag(beginTag);
                    continue;
                }

                EndTag endTag = currentElement as EndTag;
                if (endTag != null)
                {
                    OnEndTag(endTag);
                    continue;
                }

                ScriptLiteral literal = currentElement as ScriptLiteral;
                if (literal != null)
                {
                    OnScriptLiteral(literal);
                    continue;
                }

                Comment comment = currentElement as Comment;
                if (comment != null)
                {
                    OnComment(comment);
                    continue;
                }

                MarkupDirective markupDirective = currentElement as MarkupDirective;
                if (markupDirective != null)
                {
                    OnMarkupDirective(markupDirective);
                    continue;
                }

                ScriptText scriptText = currentElement as ScriptText;
                if (scriptText != null)
                {
                    OnScriptText(scriptText);
                    continue;
                }

                ScriptComment scriptComment = currentElement as ScriptComment;
                if (scriptComment != null)
                {
                    OnScriptComment(scriptComment);
                    continue;
                }

                StyleText styleText = currentElement as StyleText;
                if (styleText != null)
                {
                    OnStyleText(styleText);
                    continue;
                }

                StyleUrl styleUrl = currentElement as StyleUrl;
                if (styleUrl != null)
                {
                    OnStyleUrl(styleUrl);
                    continue;
                }

                StyleImport styleImport = currentElement as StyleImport;
                if (styleImport != null)
                {
                    OnStyleImport(styleImport);
                    continue;
                }

                StyleComment styleComment = currentElement as StyleComment;
                if (styleComment != null)
                {
                    OnStyleComment(styleComment);
                    continue;
                }

                StyleLiteral styleLiteral = currentElement as StyleLiteral;
                if (styleLiteral != null)
                {
                    OnStyleLiteral(styleLiteral);
                    continue;
                }

                Text text = currentElement as Text;
                if (text != null)
                {
                    OnText(text);
                    continue;
                }


                if (currentElement == null)
                {
                    OnDocumentEnd();
                    return;
                }

                Debug.Fail("Unrecognized element in LightWeightHTMLDocumentIterator");
            }
        }
 protected virtual void OnScriptLiteral(ScriptLiteral literal)
 {
     DefaultAction(literal);
 }