Beispiel #1
0
        protected AcceptedCharacters AcceptDottedExpression(bool isWithinCode, bool expectIdentifierFirst, params char[] allowedBrackets)
        {
            if (!expectIdentifierFirst || ParserHelpers.IsIdentifierStart(CurrentCharacter))
            {
                do
                {
                    // Parse Parentheses or Brackets if we see them
                    do
                    {
                        if (!allowedBrackets.Any(c => CurrentCharacter == c))
                        {
                            break;
                        }

                        // Dev10 884975 - Incorrect Error Messaging
                        SourceLocation bracketStart = CurrentLocation;
                        char           bracket      = CurrentCharacter;

                        if (!BalanceBrackets(allowTransition: true, spanFactory: CreateImplicitExpressionSpanFactory(isWithinCode)))
                        {
                            // Balancing terminated because of EOF
                            char terminator = _bracketPairs[bracket];
                            Context.AcceptCurrent();

                            TryRecover(RecoveryModes.Any);

                            OnError(bracketStart, RazorResources.ParseError_Expected_CloseBracket_Before_EOF, bracket, terminator);
                            return(AcceptedCharacters.Any);
                        }
                    } while (!EndOfFile);

                    // If the next character is a dot, followed by an identifier start, keep on parsing
                    using (Context.StartTemporaryBuffer()) {
                        if (CurrentCharacter != '.')
                        {
                            break;
                        }

                        Context.AcceptCurrent();

                        if (!ParserHelpers.IsIdentifierStart(CurrentCharacter))
                        {
                            if (isWithinCode)
                            {
                                Context.AcceptTemporaryBuffer();
                            }
                            break;
                        }

                        Context.AcceptTemporaryBuffer(); // Put the dot in the primary buffer
                    }

                    // Parse an identifier
                    Context.AcceptIdentifier();
                } while (!EndOfFile);
            }

            return(AcceptedCharacters.NonWhiteSpace);
        }
Beispiel #2
0
        protected virtual void AcceptWhiteSpaceByLines()
        {
            Debug.Assert(InTemporaryBuffer);

            // Eat whitespace until a non-whitespace character,
            while (Char.IsWhiteSpace(CurrentCharacter))
            {
                Context.AcceptWhiteSpace(includeNewLines: false);

                // Stopped because of a newline, so accept the newline, then accept the temporary buffer and start it again
                if (Char.IsWhiteSpace(CurrentCharacter))
                {
                    Context.AcceptLine(includeNewLineSequence: true);
                    Context.AcceptTemporaryBuffer();
                    Context.StartTemporaryBuffer();
                }
            }
        }
Beispiel #3
0
        protected bool TryParseComment(SpanFactory previousSpanFactory)
        {
            // Check for comment
            using (Context.StartTemporaryBuffer()) {
                Context.AcceptWhiteSpace(includeNewLines: true);
                if (Context.Peek(RazorParser.StartCommentSequence, caseSensitive: true))
                {
                    Context.AcceptTemporaryBuffer();
                    End(previousSpanFactory);
                }
                else
                {
                    return(false);
                }
            }

            ParseComment();
            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Parses the modeltype statement.
        /// </summary>
        /// <param name="block">The code block.</param>
        public bool ParseModelTypeStatement(CodeBlockInfo block)
        {
            Contract.Requires(block != null);

            using (StartBlock(BlockType.Directive))
            {
                block.ResumeSpans(Context);

                SourceLocation location       = CurrentLocation;
                bool           readWhitespace = RequireSingleWhiteSpace();

                End(MetaCodeSpan.Create(Context, false, readWhitespace ? AcceptedCharacters.None : AcceptedCharacters.Any));

                if (_modelOrInheritsStatementFound)
                {
                    OnError(location, "The modeltype or inherits keywords can only appear once.");
                }

                _modelOrInheritsStatementFound = true;

                // Accept Whitespace up to the new line or non-whitespace character
                Context.AcceptWhiteSpace(false);

                string typeName = null;
                if (ParserHelpers.IsIdentifierStart(CurrentCharacter))
                {
                    using (Context.StartTemporaryBuffer())
                    {
                        Context.AcceptUntil(ParserHelpers.IsNewLine);
                        typeName = Context.ContentBuffer.ToString();
                        Context.AcceptTemporaryBuffer();
                    }
                    Context.AcceptNewLine();
                }
                else
                {
                    OnError(location, "Expected model identifier.");
                }
                End(new ModelSpan(Context, typeName));
            }
            return(false);
        }
Beispiel #5
0
        private bool ParseModelStatement(CodeBlockInfo block)
        {
            using (StartBlock(BlockType.Directive)) {
                block.ResumeSpans(Context);

                SourceLocation endModelLocation = CurrentLocation;
                bool           readWhitespace   = RequireSingleWhiteSpace();

                End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: readWhitespace ? AcceptedCharacters.None : AcceptedCharacters.Any));

                if (_modelStatementFound)
                {
                    OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture, MvcResources.MvcRazorCodeParser_OnlyOneModelStatementIsAllowed, ModelTypeKeyword));
                }

                _modelStatementFound = true;

                // Accept Whitespace up to the new line or non-whitespace character
                Context.AcceptWhiteSpace(includeNewLines: false);

                string typeName = null;
                if (ParserHelpers.IsIdentifierStart(CurrentCharacter))
                {
                    using (Context.StartTemporaryBuffer()) {
                        Context.AcceptUntil(c => ParserHelpers.IsNewLine(c));
                        typeName = Context.ContentBuffer.ToString();
                        Context.AcceptTemporaryBuffer();
                    }
                    Context.AcceptNewLine();
                }
                else
                {
                    OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture, MvcResources.MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName, ModelTypeKeyword));
                }
                CheckForInheritsAndModelStatements();
                End(new ModelSpan(Context, typeName));
            }
            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Parses the model statement.
        /// </summary>
        /// <param name="block">The code block.</param>
        private bool ParseModelStatement(CodeBlockInfo block)
        {
            var location = CurrentLocation;

            bool readWhiteSpace = RequireSingleWhiteSpace();

            End(MetaCodeSpan.Create(Context, false, readWhiteSpace ? AcceptedCharacters.None : AcceptedCharacters.Any));

            if (_modelOrInheritsStatementFound)
            {
                OnError(location, "The model or inherits keywords can only appear once.");
            }

            _modelOrInheritsStatementFound = true;

            Context.AcceptWhiteSpace(false);

            string typeName = null;

            if (ParserHelpers.IsIdentifierStart(CurrentCharacter))
            {
                using (Context.StartTemporaryBuffer())
                {
                    Context.AcceptUntil(ParserHelpers.IsNewLine);
                    typeName = Context.ContentBuffer.ToString();
                    Context.AcceptTemporaryBuffer();
                }
                Context.AcceptNewLine();
            }
            else
            {
                OnError(location, "Expected model identifier.");
            }
            End(new ModelSpan(Context, typeName));
            return(false);
        }
        private bool ParseResourceStatement(CodeBlockInfo block)
        {
            End(MetaCodeSpan.Create);

            SourceLocation endModelLocation = CurrentLocation;

            if (_modelStatementFound)
            {
                OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture, "Only one '{0}' statement is allowed in a file.", ResourceKeyword));
            }

            _modelStatementFound = true;

            // Accept Whitespace up to the new line or non-whitespace character
            Context.AcceptWhiteSpace(false);

            string typeName = null;

            if (ParserHelpers.IsIdentifierStart(CurrentCharacter))
            {
                using (Context.StartTemporaryBuffer())
                {
                    // Accept a dotted-identifier, but allow <>
                    AcceptTypeName();
                    typeName = Context.ContentBuffer.ToString();
                    Context.AcceptTemporaryBuffer();
                }
            }
            else
            {
                OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture, "The '{0}' keyword must be followed by a type name on the same line.", ResourceKeyword));
            }
            CheckForInheritsAndResourceStatements();
            End(ResourceSpan.Create(Context, typeName));
            return(false);
        }
Beispiel #8
0
        private bool ParseStartPsuedoTag(Stack <TagInfo> tags, TagInfo tag)
        {
            Debug.Assert(!tag.IsEndTag, "ParseStartPsuedoTag requires a start tag");

            // Output what we've seen so far, since the "<text>" is not a markup token, it's a transition token
            if (HaveContent)
            {
                End(MarkupSpan.Create);
            }

            // Accept the "<text>"
            Context.Expect("<");
            Context.AcceptWhiteSpace(includeNewLines: true);
            Context.Expect("text");

            bool isValid = false;

            using (Context.StartTemporaryBuffer()) {
                Context.AcceptWhiteSpace(includeNewLines: true);
                if (CurrentCharacter == '/' || CurrentCharacter == '>')
                {
                    isValid = true;
                    Context.AcceptTemporaryBuffer();
                }
            }

            bool transitionComplete = false;
            bool isEmpty            = false;

            if (!isValid)
            {
                OnError(tag.Start, RazorResources.ParseError_TextTagCannotContainAttributes);
            }
            else
            {
                isEmpty = CurrentCharacter == '/';
                Context.AcceptCurrent();
                if (isEmpty)
                {
                    if (CurrentCharacter != '>')
                    {
                        OnError(CurrentLocation, RazorResources.ParseError_SlashInEmptyTagMustBeFollowedByCloseAngle);
                    }
                    else
                    {
                        transitionComplete = true;
                        Context.AcceptCurrent();
                    }
                }
                else
                {
                    transitionComplete = true;
                }
            }

            // Output the transition
            End(TransitionSpan.Create(Context, hidden: false, acceptedCharacters: transitionComplete ? AcceptedCharacters.None : AcceptedCharacters.Any));

            // Push it on to the stack and continue
            if (!isEmpty)
            {
                tags.Push(tag);
            }
            return(isEmpty);
        }
Beispiel #9
0
        protected virtual bool BalanceBrackets(bool allowTransition, SpanFactory spanFactory, bool appendOuter, char?bracket, bool useTemporaryBuffer)
        {
            spanFactory = spanFactory ?? CodeSpan.Create;

            if (useTemporaryBuffer)
            {
                Context.StartTemporaryBuffer();
            }

            int  nesting           = 0; // Nesting level
            bool callerReadBracket = true;

            if (bracket == null)
            {
                callerReadBracket = false;
                bracket           = CurrentCharacter;
            }
            else
            {
                // The caller already read the bracket, so start at nesting level 1, and also, don't append the outer bracket
                nesting = 1;
            }
            char terminator = _bracketPairs[bracket.Value];

            do
            {
                // Gather whitespace
                Context.StartTemporaryBuffer();
                AcceptWhiteSpaceByLines();

                if (CurrentCharacter == RazorParser.TransitionCharacter)
                {
                    if (Context.Peek(RazorParser.StartCommentSequence, caseSensitive: true))
                    {
                        Context.AcceptTemporaryBuffer();
                        if (useTemporaryBuffer)
                        {
                            Context.AcceptTemporaryBuffer();
                        }
                        End(spanFactory);
                        ParseComment();
                        if (useTemporaryBuffer)
                        {
                            Context.StartTemporaryBuffer();
                        }
                    }
                    else if (allowTransition)
                    {
                        Context.RejectTemporaryBuffer();
                        if (!HandleTransition(spanFactory))
                        {
                            Context.AcceptWhiteSpace(includeNewLines: true);
                            if (!TryAcceptStringOrComment())
                            {
                                Context.AssertCurrent(RazorParser.TransitionCharacter);
                                Context.AcceptCurrent();
                            }
                        }
                        else if (useTemporaryBuffer)
                        {
                            // Start a new outer temporary buffer
                            Context.StartTemporaryBuffer();
                        }
                    }
                    else
                    {
                        Context.AcceptTemporaryBuffer();
                        if (!TryAcceptStringOrComment())
                        {
                            Context.AcceptCurrent();
                        }
                    }
                }
                else
                {
                    Context.AcceptTemporaryBuffer();
                }

                AcceptUntilUnquoted(c => Char.IsWhiteSpace(c) || c == bracket || c == terminator || c == RazorParser.TransitionCharacter);
                if (CurrentCharacter == terminator)
                {
                    // If the nesting level is 1 and no bracket was specified, don't read the terminator, but we are done
                    if (nesting == 1 && callerReadBracket)
                    {
                        nesting--;
                    }
                    else
                    {
                        AcceptOrSkipCurrent(appendOuter, --nesting);
                    }
                }
                else if (CurrentCharacter == bracket)
                {
                    AcceptOrSkipCurrent(appendOuter, nesting++);
                }
            } while (!EndOfFile && nesting > 0);

            if (useTemporaryBuffer)
            {
                if (nesting > 0)
                {
                    Context.RejectTemporaryBuffer();
                }
                else
                {
                    Context.AcceptTemporaryBuffer();
                }
            }

            Debug.Assert(!InTemporaryBuffer);
            return(nesting == 0); // Return a boolean indicating if we exited because of EOF or because of the end bracket
        }