protected override bool ParseInheritsStatement(CodeBlockInfo block)
 {
     _endInheritsLocation = CurrentLocation;
     bool result = base.ParseInheritsStatement(block);
     CheckForInheritsAndModelStatements();
     return result;
 }
Пример #2
0
        protected CodeBlockInfo ParseBlockStart(bool isTopLevel, bool captureTransition)
        {
            // Capture the transition token, if any, into a span
            Span transitionSpan = null;

            if (HaveContent && captureTransition)
            {
                transitionSpan = TransitionSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None);
                Context.ResetBuffers();
            }

            SourceLocation start      = CurrentLocation;
            string         identifier = Context.AcceptIdentifier();

            Span initialSpan = null;

            if (isTopLevel)
            {
                initialSpan = CodeSpan.Create(Context);
                Context.ResetBuffers();
            }

            CodeBlockInfo block = new CodeBlockInfo(identifier, start, isTopLevel, transitionSpan, initialSpan);

            return(block);
        }
Пример #3
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 ParseModelStatement(CodeBlockInfo block) {
            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, ModelKeyword));
            }

            _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, ModelKeyword));
            }
            CheckForInheritsAndModelStatements();
            End(new ModelSpan(Context, typeName));
            return false;
        }
        private bool ParseModelStatement(CodeBlockInfo block)
        {
            var currentLocation = this.CurrentLocation;
            var acceptedCharacters = this.RequireSingleWhiteSpace() ? AcceptedCharacters.None : AcceptedCharacters.Any;

            this.End(MetaCodeSpan.Create(this.Context, false, acceptedCharacters));

            if (this.modelStatementFound)
                this.OnError(currentLocation, string.Format(CultureInfo.CurrentCulture, "Only one @model statement is allowed."));

            this.modelStatementFound = true;
            this.Context.AcceptWhiteSpace(false);
            string modelTypeName = null;
            if (ParserHelpers.IsIdentifierStart(this.CurrentCharacter))
            {
                using (this.Context.StartTemporaryBuffer())
                {
                    this.Context.AcceptUntil(c => ParserHelpers.IsNewLine(c));
                    modelTypeName = this.Context.ContentBuffer.ToString();
                    this.Context.AcceptTemporaryBuffer();
                }
                this.Context.AcceptNewLine();
            }
            else
            {
                this.OnError(currentLocation, string.Format(CultureInfo.CurrentCulture, "@model must be followed by a type name."));
            }

            this.CheckForInheritsAndModelStatements();
            this.End(new ModelSpan(this.Context, modelTypeName));
            return false;
        }
 protected override bool ParseInheritsStatement(CodeBlockInfo block)
 {
     this.endInheritsLocation = this.CurrentLocation;
     var result = this.ParseInheritsStatement(block);
     this.CheckForInheritsAndModelStatements();
     return result;
 }
        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;
        }
Пример #8
0
        /// <summary>
        /// Parses the inherits statement.
        /// </summary>
        /// <param name="block">The code block.</param>
        protected override bool ParseInheritsStatement(CodeBlockInfo block)
        {
            var location = CurrentLocation;

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

            _modelOrInheritsStatementFound = true;

            return base.ParseInheritsStatement(block);
        }
Пример #9
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;
        }
Пример #10
0
        private bool ParseUsingStatement(CodeBlockInfo block) {
            if (block.IsTopLevel) {
                Context.ResumeSpan(block.InitialSpan);
            }

            using (Context.StartTemporaryBuffer()) {
                // Skip whitespace by lines
                Context.AcceptWhiteSpace(includeNewLines: false);

                if (CurrentCharacter == '(') {
                    Context.AcceptTemporaryBuffer();

                    // Parse like a regular control flow statement
                    if (block.IsTopLevel) {
                        block.InitialSpan = CodeSpan.Create(Context);
                        Context.ResetBuffers();

                        StartBlock(BlockType.Statement);
                        block.ResumeSpans(Context);
                    }
                    return ParseConditionalBlockStatement(block);
                }
                else if (!block.IsTopLevel) {
                    Context.RejectTemporaryBuffer();

                    // Not the right kind of using for this block.  We're not in a top-level block and we saw a namespace import or type alias
                    OnError(block.Start, RazorResources.ParseError_NamespaceImportAndTypeAlias_Cannot_Exist_Within_CodeBlock);
                }
                else if (ParserHelpers.IsIdentifierStart(CurrentCharacter)) {
                    Context.RejectTemporaryBuffer();

                    // Parse a namespace import
                    block.InitialSpan = CodeSpan.Create(Context);
                    Context.ResetBuffers();

                    StartBlock(BlockType.Directive);
                    block.ResumeSpans(Context);
                    ParseNamespaceImport();
                    return true;
                }
                else {
                    if (block.IsTopLevel) {
                        Context.AcceptTemporaryBuffer();

                        block.InitialSpan = CodeSpan.Create(Context);
                        Context.ResetBuffers();

                        StartBlock(BlockType.Statement);
                        block.ResumeSpans(Context);
                    }
                }
            }
            return false;
        }
Пример #11
0
        protected internal virtual bool ParseIfStatement(CodeBlockInfo block) {
            SourceLocation errorLocation = CurrentLocation;

            // Parse the body
            ParseConditionalBlockStatement(block);

            // Parse the attached branches
            do {
                // Start a temporary buffer just in case we don't see the branch we expected
                Context.StartTemporaryBuffer();
                AcceptWhiteSpaceAndComments();
                errorLocation = CurrentLocation;

                // If the first character after the whitespace isn't an identifier, or comment we're done
                // If the first character is an identifier but isn't "else", we're also done
                if (!ParserHelpers.IsIdentifierStart(CurrentCharacter) ||
                    !String.Equals("else", Context.AcceptIdentifier(), StringComparison.Ordinal)) {
                    Context.RejectTemporaryBuffer();
                    break;
                }
                else {
                    Context.AcceptTemporaryBuffer();
                }

                bool isElseIf = false;
                using (Context.StartTemporaryBuffer()) {
                    Context.AcceptWhiteSpace(includeNewLines: true);

                    // Now, we need to check for "else if"
                    if (ParserHelpers.IsIdentifierStart(CurrentCharacter) && String.Equals("if", Context.AcceptIdentifier(), StringComparison.Ordinal)) {
                        isElseIf = true;
                        // It's an else if branch, parse a condition AND a body
                        Context.AcceptTemporaryBuffer();
                        Context.AcceptWhiteSpace(includeNewLines: true);
                        ParseConditionalBlockStatement(new CodeBlockInfo("else if", errorLocation, false));
                    }
                    else if (CurrentCharacter == '{') {
                        // It's a valid else
                        Context.AcceptTemporaryBuffer();
                    }
                    else {
                        // Brace-less else
                        OnError(CurrentLocation, RazorResources.ParseError_SingleLine_ControlFlowStatements_Not_Allowed, "{", CurrentCharacter);
                    }
                }

                // Have to do this because the using() {} block can't overlap with the if and we want the temporary buffer cleared up before this point
                if (!isElseIf) {
                    // It's an else branch, just parse a body

                    CodeBlockInfo elseBlock = new CodeBlockInfo("else", errorLocation, false);
                    if (CurrentCharacter == '{') {
                        return ParseCodeBlock(elseBlock, bracesAreMetacode: false);
                    }
                    else {
                        ParseStatement(elseBlock);
                        return false;
                    }
                }
            } while (!EndOfFile);
            return false;
        }
Пример #12
0
        protected internal virtual bool ParseCaseBlock(CodeBlockInfo block) {
            // TODO: Only allow case and default statements directly within switch statement
            // Parse until the ':'
            Context.AcceptUntilInclusive(':');

            while (!EndOfFile) {
                using (Context.StartTemporaryBuffer()) {
                    Context.AcceptWhiteSpace(includeNewLines: true);
                    string identifier = Context.AcceptIdentifier();
                    if (String.Equals(identifier, "case", StringComparison.OrdinalIgnoreCase) ||
                        String.Equals(identifier, "default", StringComparison.OrdinalIgnoreCase)) {
                        // Reached the next case block
                        break;
                    }
                    else if (CurrentCharacter == '}') {
                        // Reached the end of the switch, but we don't handle the '}'
                        break;
                    }
                }

                ParseStatement(block);
            }
            return false;
        }
Пример #13
0
        protected internal virtual bool ParseTryStatement(CodeBlockInfo block) {
            // Parse the body
            ParseControlFlowBody(block);

            // Check for additional clauses
            bool allowAdditionalClauses = false;
            do {
                allowAdditionalClauses = false;
                Context.StartTemporaryBuffer();
                AcceptWhiteSpaceAndComments();
                if (!ParserHelpers.IsIdentifierStart(CurrentCharacter)) {
                    Context.RejectTemporaryBuffer();
                }
                else {
                    SourceLocation blockStart = CurrentLocation;
                    string identifier = Context.AcceptIdentifier();
                    if (String.Equals(identifier, "catch")) {
                        Context.AcceptTemporaryBuffer();
                        ParseConditionalBlockStatement(new CodeBlockInfo("catch", blockStart, false));
                        allowAdditionalClauses = true;
                    }
                    else if (String.Equals(identifier, "finally")) {
                        Context.AcceptTemporaryBuffer();

                        // After the "finally" we know we're done, but only if it's complete
                        return ParseControlFlowBody(new CodeBlockInfo("finally", blockStart, false));
                    }
                    else {
                        Context.RejectTemporaryBuffer();
                    }
                }
            } while (allowAdditionalClauses);
            return false;
        }
Пример #14
0
        protected internal virtual bool ParseDoStatement(CodeBlockInfo block) {
            // Parse the body
            bool bodyComplete = ParseControlFlowBody(block);

            // Check for a while clause and return if it's not there (C# requires it, but there's no real reason we need to, C# can report the error if it's missing)
            Context.StartTemporaryBuffer();
            AcceptWhiteSpaceAndComments();
            if (!Context.Peek("while", caseSensitive: true)) {
                Context.RejectTemporaryBuffer();
                return false;
            }
            Context.AcceptTemporaryBuffer();

            // Parse the while clause
            string whileKeyword = Context.AcceptIdentifier();
            Debug.Assert(whileKeyword == "while");

            Context.AcceptWhiteSpace(includeNewLines: true);
            if (CurrentCharacter == '(') {
                SourceLocation errorLocation = CurrentLocation;
                if (!BalanceBrackets()) {
                    Context.AcceptLine(includeNewLineSequence: false);
                    OnError(errorLocation, RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")");
                }
            }
            if (CurrentCharacter == ';') {
                Context.AcceptCurrent();
                return bodyComplete; // The while clause is complete
            }
            return false;
        }
Пример #15
0
        private bool ParseFunctionsBlock(CodeBlockInfo block) {
            Debug.Assert(block.IsTopLevel, "Class blocks are only allowed at the top level");

            Context.ResumeSpan(block.InitialSpan);
            using (Context.StartTemporaryBuffer()) {
                Context.AcceptWhiteSpace(includeNewLines: true);
                if (CurrentCharacter == '{') {
                    Context.AcceptWhiteSpace(includeNewLines: true);
                }
                else {
                    Context.RejectTemporaryBuffer();

                    block.InitialSpan = CodeSpan.Create(Context);
                    Context.ResetBuffers();

                    StartBlock(BlockType.Expression);
                    block.ResumeSpans(Context);
                    ParseImplicitExpression(block);
                    return false;
                }
            }

            block.InitialSpan = MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None);
            Context.ResetBuffers();

            StartBlock(BlockType.Functions);
            block.ResumeSpans(Context);

            return ParseDelimitedBlock(block, useErrorRecovery: false, autoCompleteString: "}");
        }
Пример #16
0
 private bool ParseImplicitExpression(CodeBlockInfo block) {
     return ParseImplicitExpression(block, acceptTrailingDot: false);
 }
Пример #17
0
        private bool ParseImportsStatement(CodeBlockInfo block) {
            using (StartBlock(BlockType.Directive)) {
                string ns = String.Empty;
                block.ResumeSpans(Context);
                using (Context.StartTemporaryBuffer()) {
                    Context.AcceptWhiteSpace(includeNewLines: false);
                    if (ParserHelpers.IsIdentifierStart(CurrentCharacter)) {
                        Context.AcceptIdentifier();
                        if (CurrentCharacter == '.') {
                            // Definitely a namespace import
                            Context.AcceptCurrent();
                            AcceptTypeName(allowGenerics: false);
                        }
                        else {
                            // Could be an alias, need to check what's after whitespace
                            using (Context.StartTemporaryBuffer()) {
                                Context.AcceptWhiteSpace(includeNewLines: false);
                                if (CurrentCharacter == '=') {
                                    Context.AcceptTemporaryBuffer();
                                    Context.AcceptCurrent();
                                    Context.AcceptWhiteSpace(includeNewLines: false);
                                    if (ParserHelpers.IsIdentifierStart(CurrentCharacter)) {
                                        AcceptTypeName();
                                    }
                                    else {
                                        OnError(CurrentLocation, RazorResources.ParseError_NamespaceOrTypeAliasExpected);
                                    }
                                }
                            }
                        }

                        // Capture the content of the temporary buffer as the namespace
                        ns = Context.ContentBuffer.ToString();
                    }
                    else {
                        OnError(CurrentLocation, RazorResources.ParseError_NamespaceOrTypeAliasExpected);
                    }
                    Context.AcceptTemporaryBuffer();
                    
                    // Capture trailing whitespace to the end of the line
                    Context.AcceptWhiteSpace(includeNewLines: false);
                    if (ParserHelpers.IsNewLine(Context.CurrentCharacter)) {
                        Context.AcceptNewLine();
                    }
                }
                End(NamespaceImportSpan.Create(Context, acceptedCharacters: AcceptedCharacters.Any, kind: SpanKind.MetaCode, ns: ns, namespaceKeywordLength: ImportsKeywordLength));
            }
            return true;
        }
Пример #18
0
        // Example statements:
        //  foreach(var f in Foo) [statement]
        //  { [statement-list] }
        //  <tag>[markup]</tag>
        protected internal virtual void ParseStatement(CodeBlockInfo block) {
            // Check for markup, because that will change the whitespace handling

            // Dev10 Bug 884969 - Emit space between markup and code
            // Whitespace ownership rules:
            //  * If there's no markup on a line, all the whitespace (including the trailing newline) belongs to code
            //  * Markup owns all markup from its start character back to, but excluding, the preceding  newline (or the start of code)
            //  * Markup owns all markup from its end character up to, and including, the trailing newline (or the start of code)
            Context.StartTemporaryBuffer();

            // Eat whitespace until a non-whitespace character, 
            AcceptWhiteSpaceByLines();

            // Error Detection: Check for @<p>Foo</p> and display an error
            if (CurrentCharacter == RazorParser.TransitionCharacter && Context.MarkupParser.NextIsTransition(allowImplicit: true, allowExplicit: false)) {
                Context.AcceptTemporaryBufferInDesignTimeMode();
                ParseInvalidMarkupSwitch();
                return;
            }
            // It's markup, so the whitespace belongs to the markup at runtime
            else if (Context.MarkupParser.IsAtImplicitTransition() ||
                (CurrentCharacter == RazorParser.TransitionCharacter && Context.MarkupParser.NextIsTransition(allowImplicit: false, allowExplicit: true))) {
                Context.AcceptTemporaryBufferInDesignTimeMode();
                ParseBlockWithOtherParser(previousSpanFactory: CodeSpan.Create);
                return;
            }

            // No markup on this line, so it's whitespace belongs to code.
            Context.AcceptTemporaryBuffer();

            // Ok, not markup at this point, so check for C# statements and other statements
            if (ParserHelpers.IsIdentifierStart(CurrentCharacter)) {
                CodeBlockInfo subBlock = ParseBlockStart(isTopLevel: false, captureTransition: false);
                BlockParser parser = GetBlockParser(subBlock, null);
                if (parser != null) {
                    // Block type is always the same as the current one since Plan9 Keywords aren't allowed here, so merge it into the current block
                    parser(subBlock);
                }
                else {
                    AcceptStatementToSemicolon();
                }
            }
            // Use the first character to determine if it's something we need to handle specially
            else if (CurrentCharacter == RazorParser.TransitionCharacter) {
                if (!TryParseComment(previousSpanFactory: CodeSpan.Create)) {
                    // "@[expr]" ==> Shorthand for Write([expr]);
                    ParseEmbeddedExpression();
                }
            }
            else if (CurrentCharacter == '{') {
                // "{ [statement-list] }" ==> Start of a code block
                ParseCodeBlock(block, bracesAreMetacode: false);
            }
            else if (IsCommentStart()) {
                AcceptComment();
            }
            else if (CurrentCharacter != '}') {
                // Nothing interesting, so just read to the ';'
                AcceptStatementToSemicolon();
            }
        }
Пример #19
0
        protected internal virtual bool ParseInheritsStatement(CodeBlockInfo block) {
            SourceLocation endInheritsLocation = Context.CurrentLocation;
            bool readWhitespace = RequireSingleWhiteSpace();
            End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: readWhitespace ? AcceptedCharacters.None : AcceptedCharacters.Any));

            // 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()) {
                    // Accept a dotted-identifier, but allow <>
                    Context.AcceptLine(includeNewLineSequence: false);
                    typeName = Context.ContentBuffer.ToString();
                    Context.AcceptTemporaryBuffer();
                }
                Context.AcceptNewLine();
            }
            else {
                OnError(endInheritsLocation, RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName);
            }

            if (HaveContent || readWhitespace) {
                End(InheritsSpan.Create(Context, typeName));
            }

            return false;
        }
Пример #20
0
        private bool ParseCodeBlock(CodeBlockInfo block, bool bracesAreMetacode, bool acceptBraces = true) {
            bool success = false;

            if (acceptBraces) {
                Context.AcceptCurrent(); // "{"
            }
            Span openBraceSpan = null;
            if (bracesAreMetacode) {
                openBraceSpan = MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None);
                End(openBraceSpan);
            }

            while (!EndOfFile && CurrentCharacter != '}') {
                ParseStatement(block);
            }

            if (bracesAreMetacode) {
                if (!Context.PreviousSpanCanGrow || HaveContent) {
                    End(CodeSpan.Create(Context));
                }
            }

            Context.FlushNextOutputSpan();

            if (CurrentCharacter == '}') {
                success = true;
                if (acceptBraces) {
                    Context.AcceptCurrent();
                    if (bracesAreMetacode) {
                        End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None));
                    }
                }
            }
            else {
                if (openBraceSpan != null && openBraceSpan.Next != null && openBraceSpan.Next is CodeSpan) {
                    openBraceSpan.Next.AutoCompleteString = "}";
                }
                OnError(block.Start, RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, block.Name, '}', '{');
            }

            return success;
        }
Пример #21
0
 protected bool HandleReservedWord(CodeBlockInfo block) {
     StartBlock(BlockType.Directive);
     block.ResumeSpans(Context);
     End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None));
     OnError(block.Start, String.Format(CultureInfo.CurrentCulture, RazorResources.ParseError_ReservedWord, block.Name));
     return true;
 }
Пример #22
0
 private BlockParser GetBlockParser(CodeBlockInfo block, BlockParser fallbackParser, out bool isStatementBlock) {
     BlockParser parser = null;
     isStatementBlock = true;
     if (block.Name == null || !_identifierHandlers.TryGetValue(block.Name, out parser)) {
         isStatementBlock = false;
         if (block.Name == null || !block.IsTopLevel || !RazorKeywords.TryGetValue(block.Name, out parser)) {
             parser = fallbackParser;
         }
     }
     return parser;
 }
Пример #23
0
 private BlockParser GetBlockParser(CodeBlockInfo block, BlockParser fallbackParser) {
     bool _ = false; // Don't care in this case
     return GetBlockParser(block, fallbackParser, out _);
 }
Пример #24
0
        private bool ParseHelperBlock(CodeBlockInfo block) {
            SourceLocation errorLocation = CurrentLocation;
            bool readWhitespace = RequireSingleWhiteSpace();
            End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: readWhitespace ? AcceptedCharacters.None : AcceptedCharacters.Any));

            // Accept whitespace
            Context.AcceptWhiteSpace(includeNewLines: false);

            // Check for an identifier
            bool seenError = String.IsNullOrEmpty(
                Context.ExpectIdentifier(RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start, allowPrecedingWhiteSpace: true, errorLocation: errorLocation));

            // Check for parameter list
            errorLocation = CurrentLocation;
            Context.AcceptWhiteSpace(includeNewLines: false);
            bool seenOpenBracket = Context.Expect('(', outputError: !seenError, errorMessage: RazorResources.ParseError_MissingCharAfterHelperName, caseSensitive: true, errorLocation: errorLocation);
            seenError |= !seenOpenBracket;
            errorLocation = CurrentLocation;

            if (seenOpenBracket) {
                if (BalanceBrackets(allowTransition: false, spanFactory: null, appendOuter: true, bracket: '(', useTemporaryBuffer: false)) {
                    Context.Expect(')', outputError: !seenError);
                }
                else if (!seenError) {
                    seenError = true;
                    OnError(errorLocation, RazorResources.ParseError_UnterminatedHelperParameterList);
                }
            }

            bool outputtedHeader = false;
            Span headerSpan = null;
            using (Context.StartTemporaryBuffer()) {
                Context.AcceptWhiteSpace(includeNewLines: true);
                errorLocation = CurrentLocation;
                if (Context.Expect('{', outputError: !seenError, errorMessage: RazorResources.ParseError_MissingCharAfterHelperParameters)) {
                    Context.AcceptTemporaryBuffer();
                    if (HaveContent) {
                        outputtedHeader = true;
                        // Can't grow at the end since we saw "{"
                        headerSpan = HelperHeaderSpan.Create(Context, !seenError, AcceptedCharacters.Any);
                        End(headerSpan);
                        Context.FlushNextOutputSpan();
                    }

                    using (Context.StartBlock(BlockType.Statement, outputCurrentBufferAsTransition: false)) {
                        ParseCodeBlock(block, bracesAreMetacode: false, acceptBraces: false);
                        End(CodeSpan.Create);
                        Context.FlushNextOutputSpan();
                    }

                    if (CurrentCharacter != '}') {
                        if (headerSpan != null) {
                            headerSpan.AutoCompleteString = "}";
                        }
                    }
                    else {
                        headerSpan.AcceptedCharacters = AcceptedCharacters.None;
                        Context.AcceptCurrent();
                        End(HelperFooterSpan.Create);
                        return true; // Helper block can't grow any more
                    }
                }
                else {
                    seenError = true;
                    Context.RejectTemporaryBuffer();
                    Context.AcceptWhiteSpace(includeNewLines: false);
                }
            }

            if (!outputtedHeader && readWhitespace) {
                // In an error case, we need to classify whatever we did capture as HelperHeader
                End(HelperHeaderSpan.Create(Context, !seenError));
            }
            return false;
        }
Пример #25
0
        protected internal virtual bool ParseConditionalBlockStatement(CodeBlockInfo block) {
            Context.AcceptWhiteSpace(includeNewLines: true);

            if (CurrentCharacter == '(') {
                SourceLocation errorLocation = CurrentLocation;
                // Balance parens
                if (!BalanceBrackets()) {
                    Context.AcceptLine(includeNewLineSequence: false);
                    OnError(errorLocation, RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")");
                    return false;
                }
            }

            return ParseControlFlowBody(block);
        }
Пример #26
0
        private bool ParseSectionBlock(CodeBlockInfo block) {
            RequireSingleWhiteSpace();
            Context.AcceptWhiteSpace(includeNewLines: false);
            bool complete = false;
            string sectionName = Context.ExpectIdentifier(RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start);
            if (sectionName == null) {
                End(SectionHeaderSpan.Create(Context, sectionName: String.Empty, acceptedCharacters: AcceptedCharacters.Any));
            }
            else {
                Context.AcceptWhiteSpace(includeNewLines: false);
                using (Context.StartTemporaryBuffer()) {
                    Context.AcceptWhiteSpace(includeNewLines: true);
                    if (CurrentCharacter != '{') {
                        Context.RejectTemporaryBuffer();
                        OnError(CurrentLocation, RazorResources.ParseError_MissingOpenBraceAfterSection);
                        End(SectionHeaderSpan.Create(Context, sectionName, acceptedCharacters: AcceptedCharacters.Any));
                        return false;
                    }
                    else {
                        Context.AcceptTemporaryBuffer();
                    }
                }
                Context.AcceptCurrent(); // {

                SectionHeaderSpan headerSpan = SectionHeaderSpan.Create(Context, sectionName, acceptedCharacters: AcceptedCharacters.Any);
                End(headerSpan);

                Context.SwitchActiveParser();
                Context.MarkupParser.ParseSection(Tuple.Create("{", "}"), caseSensitive: true);
                Context.SwitchActiveParser();

                if (Context.CurrentCharacter == '}') {
                    complete = true;
                    Context.AcceptCurrent(); // }
                    End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None));
                }
                else {
                    headerSpan.AutoCompleteString = "}";
                }

            }
            return complete;
        }
Пример #27
0
        protected internal virtual bool ParseControlFlowBody(CodeBlockInfo block) {
            bool success = true;
            using (Context.StartTemporaryBuffer()) {
                Context.AcceptWhiteSpace(includeNewLines: true);

                if (CurrentCharacter != '{') {
                    success = false;
                    OnError(CurrentLocation, RazorResources.ParseError_SingleLine_ControlFlowStatements_Not_Allowed, "{", CurrentCharacter);
                }
                else {
                    Context.AcceptTemporaryBuffer();
                }
            }

            if (success) {
                // We know for sure it's a code block
                return ParseCodeBlock(block, bracesAreMetacode: false);
            }
            else {
                // Error recovery, let's just accept a statement
                ParseStatement(block);
                return false; // Not complete yet though
            }
        }
Пример #28
0
        private bool ParseDelimitedBlock(CodeBlockInfo block, bool allowTransition = true, bool useErrorRecovery = true, string autoCompleteString = null) {
            Context.AcceptWhiteSpace(includeNewLines: true);

            // Append the open bracket as a metacode token
            char bracket = CurrentCharacter;
            if (!_bracketPairs.ContainsKey(bracket)) {
                throw new InvalidOperationException(RazorResources.ParseDelimitedBlock_Requires_Bracket);
            }
            char terminator = _bracketPairs[bracket];

            Context.AcceptCurrent();
            End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None));

            // Append the terminator as a metacode token
            bool complete = BalanceBrackets(allowTransition: allowTransition, spanFactory: null, appendOuter: false, bracket: bracket, useTemporaryBuffer: useErrorRecovery);
            if (!complete) {
                if (useErrorRecovery) {
                    // Try to recover
                    TryRecover(RecoveryModes.Markup | RecoveryModes.Transition);
                }

                End(CodeSpan.Create(Context, autoCompleteString));
                OnError(block.Start, RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, block.Name, terminator, bracket);
            }
            else {
                End(CodeSpan.Create);
                Context.AcceptCurrent();
                End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None));
            }
            return complete;
        }
Пример #29
0
 private bool ParseImplicitExpression(CodeBlockInfo block, bool acceptTrailingDot) {
     bool expectIdentifierFirst = block.Name == null;
     block.Name = RazorResources.BlockName_ImplicitExpression;
     using (StartBlock(BlockType.Expression)) {
         block.ResumeSpans(Context);
         AcceptedCharacters accepted = AcceptDottedExpression(acceptTrailingDot, expectIdentifierFirst, '(');
         End(ImplicitExpressionSpan.Create(Context, TopLevelKeywords, acceptTrailingDot, accepted));
         return true;
     }
 }
Пример #30
0
 // @[not a block statement keyword]
 protected internal virtual bool ParseImplicitExpression(CodeBlockInfo block) {
     return ParseImplicitExpression(block, isWithinCode: false, expectIdentifierFirst: false);
 }
Пример #31
0
        protected internal virtual bool ParseImplicitExpression(CodeBlockInfo block, bool isWithinCode, bool expectIdentifierFirst) {
            // TODO: Refactor this into better block creation logic
            block.Name = RazorResources.BlockName_ImplicitExpression;

            AcceptedCharacters accepted = AcceptDottedExpression(isWithinCode, expectIdentifierFirst, '(', '[');
            End(ImplicitExpressionSpan.Create(Context, TopLevelKeywords, isWithinCode, accepted));

            return true; // Return value doesn't matter since we're creating the span here.
        }