Beispiel #1
0
        /// <summary>
        /// Tokenizes a block of whitespace.
        /// </summary>
        /// <returns>The state result.</returns>
        private StateResult WhiteSpace()
        {
            TakeUntil(c => !ParserHelpers.IsWhiteSpace(c) && !ParserHelpers.IsNewLine(c));
            if (HaveContent)
            {
                return(Transition(EndSymbol(HandlebarsSymbolType.WhiteSpace), Data));
            }

            return(Transition(Data));
        }
Beispiel #2
0
        /// <summary>
        /// Represents the default state of the tokenizer.
        /// </summary>
        /// <returns>The state result.</returns>
        private StateResult Data()
        {
            if (EndOfFile)
            {
                if (HaveContent)
                {
                    return(Transition(EndSymbol(HandlebarsSymbolType.Text), Stop));
                }

                return(Stop());
            }

            if (ParserHelpers.IsWhiteSpace(CurrentCharacter) || ParserHelpers.IsNewLine(CurrentCharacter))
            {
                if (HaveContent)
                {
                    return(Transition(EndSymbol(HandlebarsSymbolType.Text), WhiteSpace));
                }

                return(Transition(WhiteSpace));
            }

            TakeUntil(c => c == '{' || ParserHelpers.IsWhiteSpace(c));

            if (ParserHelpers.IsWhiteSpace(CurrentCharacter))
            {
                return(Stay());
            }

            if (HaveContent && CurrentCharacter == '{')
            {
                if (Buffer[Buffer.Length - 1] == '\\')
                {
                    // The { character is being escaped, so move on.
                    TakeCurrent();
                    return(Stay());
                }

                if (Peek() == '{')
                {
                    // We're at the start of a tag.
                    return(Transition(EndSymbol(HandlebarsSymbolType.Text), BeginTag));
                }
            }
            if (Peek() == '{')
            {
                // We're at the start of a tag.
                return(Transition(BeginTag));
            }

            TakeCurrent();

            return(Stay());
        }
Beispiel #3
0
        /// <summary>
        /// Continues the content of the tag.
        /// </summary>
        /// <param name="raw">True if we are expected a raw tag.</param>
        /// <returns>The state result.</returns>
        private StateResult ContinueTagContent(bool raw)
        {
            if (CurrentCharacter == '@')
            {
                TakeCurrent();

                return(Stay(EndSymbol(HandlebarsSymbolType.At)));
            }

            if (HandlebarsHelpers.IsIdentifierStart(CurrentCharacter))
            {
                return(Identifier());
            }

            if (Char.IsDigit(CurrentCharacter))
            {
                return(NumericLiteral());
            }

            switch (CurrentCharacter)
            {
            case '.':
            {
                TakeCurrent();
                if (CurrentCharacter == '/')
                {
                    // We've matched a link to the current context.
                    TakeCurrent();
                    return(Stay(EndSymbol(HandlebarsSymbolType.CurrentContext)));
                }

                if (CurrentCharacter == '.' && Peek() == '/')
                {
                    // We've matched a link to the parent context.
                    TakeCurrent();
                    TakeCurrent();
                    return(Stay(EndSymbol(HandlebarsSymbolType.ParentContext)));
                }

                // We've matched a dot, which could be part of an expression.
                return(Stay(EndSymbol(HandlebarsSymbolType.Dot)));
            }

            case '/':
            {
                TakeCurrent();
                // We've matched a forward-slash, which could be part of an expression.
                return(Stay(EndSymbol(HandlebarsSymbolType.Slash)));
            }

            case ' ':
            {
                // Take all the available whitespace.
                TakeUntil(c => !ParserHelpers.IsWhiteSpace(c));
                return(Stay(EndSymbol(HandlebarsSymbolType.WhiteSpace)));
            }

            case '~':
            {
                TakeCurrent();
                // We've reached a '~' character, so jump to the end of the tag.
                return(Transition(EndSymbol(HandlebarsSymbolType.Tilde), () => EndTag(raw)));
            }

            case '"':
            case '\'':
            {
                var quote = CurrentCharacter;
                TakeCurrent();
                // We've reached a quoted literal.
                return(QuotedLiteral(quote));
            }

            case '=':
            {
                // We're reached a map assignment.
                TakeCurrent();
                return(Stay(EndSymbol(HandlebarsSymbolType.Assign)));
            }

            case '}':
            {
                // We've reached a closing tag, so transition away.
                return(Transition(() => EndTag(raw)));
            }

            default:
            {
                CurrentErrors.Add(new Error("Unexpected character: " + CurrentCharacter, CurrentLocation));
                return(Transition(Stop));
            }
            }
        }
Beispiel #4
0
 /// <summary>
 /// Returns a predicate that determines if the given character is a character or whitespace (including new lines).
 /// </summary>
 /// <param name="character">The character.</param>
 /// <returns></returns>
 protected Func <char, bool> CharOrWhiteSpace(char character)
 {
     return(c => c == character || ParserHelpers.IsWhiteSpace(character) || ParserHelpers.IsNewLine(character));
 }