private bool ParseModelStatement(CodeBlockInfo block)
        {
            using (this.StartBlock(BlockType.Directive))
            {
                block.ResumeSpans(this.Context);
                var currentLocation = 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 @ModelType 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, "@ModelType must be followed by a type name."));
                }
                this.CheckForInheritsAndModelStatements();
                this.End(new ModelSpan(this.Context, modelTypeName));
            }
            return false;
        }
        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;
        }
        /// <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;
        }
        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: "}");
        }
        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;
        }
 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;
 }
 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;
     }
 }
        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;
        }
        private bool ParseOptionStatement(CodeBlockInfo block) {
            using (StartBlock(BlockType.Directive)) {
                block.ResumeSpans(Context);
                Context.AcceptWhiteSpace(includeNewLines: true);

                // Read the next two identifiers with interleaved whitespace
                // TODO: Error checking
                SourceLocation errorLocation = CurrentLocation;
                string option = Context.AcceptIdentifier();

                string codeDomOptionName = null;
                bool flag = true; // Default to whatever the "on" value is
                if (String.Equals(option, "strict", StringComparison.OrdinalIgnoreCase)) {
                    codeDomOptionName = OptionStrictCodeDomName;
                    flag = false; // Strict On == AllowLateBinding Off
                }
                else if (String.Equals(option, "explicit", StringComparison.OrdinalIgnoreCase)) {
                    // Explicit On = RequireVariableDeclaration On
                    codeDomOptionName = OptionExplicitCodeDomName;
                }
                else {
                    OnError(errorLocation, RazorResources.ParseError_UnknownOption, option);
                }

                if (codeDomOptionName != null) {
                    Context.AcceptWhiteSpace(includeNewLines: true);
                    string value = Context.AcceptIdentifier();
                    if (String.Equals(value, "off", StringComparison.OrdinalIgnoreCase)) {
                        // Flip the flag to it's "off" value
                        flag = !flag;
                    }
                    else if (!String.Equals(value, "on", StringComparison.OrdinalIgnoreCase)) {
                        // Not ON or OFF ==> Error
                        OnError(errorLocation, RazorResources.ParseError_InvalidOptionValue, option, value);
                    }
                }
                End(VBOptionSpan.Create(Context, codeDomOptionName, flag));
            }
            return true;
        }
        protected virtual bool ParseInheritsStatement(CodeBlockInfo block) {
            using (StartBlock(BlockType.Directive)) {
                block.ResumeSpans(Context);
                SourceLocation endInheritsLocation = 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 true;
        }
        private bool ParseSectionStatement(CodeBlockInfo block) {
            using (StartBlock(BlockType.Section)) {
                block.ResumeSpans(Context);
                RequireSingleWhiteSpace();
                AcceptWhitespaceWithVBNewlines();
                string sectionName = Context.ExpectIdentifier(RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
                                                              allowPrecedingWhiteSpace: false);
                SectionHeaderSpan headerSpan = SectionHeaderSpan.Create(Context, sectionName ?? String.Empty, acceptedCharacters: AcceptedCharacters.Any);
                End(headerSpan);

                // Parse a section
                Context.SwitchActiveParser();
                Context.MarkupParser.ParseSection(Tuple.Create((string)null, "end section"), caseSensitive: false);
                Context.SwitchActiveParser();

                // Expect "End Section" (Expect will throw errors if they aren't there)
                if (EndOfFile) {
                    OnError(block.Start, RazorResources.ParseError_BlockNotTerminated, "Section", EndSectionKeyword);
                    headerSpan.AutoCompleteString = EndSectionKeyword;
                    return true;
                }

                bool success = false;
                if (Context.Expect("end", outputError: true, errorMessage: null, caseSensitive: false)) {
                    Context.AcceptWhiteSpace(includeNewLines: true);
                    success = Context.Expect("section", outputError: true, errorMessage: null, caseSensitive: false);
                }
                if (!success) {
                    headerSpan.AutoCompleteString = EndSectionKeyword;
                }
                End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: AcceptedCharacters.None));
            }
            return true;
        }
        private bool ParseHelperBlock(CodeBlockInfo block) {
            using (StartBlock(BlockType.Helper)) {
                block.ResumeSpans(Context);
                SourceLocation errorLocation = CurrentLocation;
                // If we see a new line then bail out early
                bool ateNewLine = ParserHelpers.IsNewLine(CurrentCharacter);
                bool readWhitespace = RequireSingleWhiteSpace();
                End(MetaCodeSpan.Create(Context, hidden: false, acceptedCharacters: readWhitespace ? AcceptedCharacters.None : AcceptedCharacters.Any));

                if (ateNewLine) {
                    return true;
                }

                // Accept whitespace
                AcceptWhitespaceWithVBNewlines();

                // 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;
                AcceptWhitespaceWithVBNewlines();
                bool outputtedHeader = false;
                if (Context.Expect('(', outputError: !seenError, errorMessage: RazorResources.ParseError_MissingCharAfterHelperName, caseSensitive: false, errorLocation: errorLocation)) {
                    errorLocation = CurrentLocation;
                    if (!BalanceBrackets(allowTransition: false, spanFactory: null, appendOuter: true, bracket: '(', useTemporaryBuffer: false)) {
                        OnError(errorLocation, RazorResources.ParseError_UnterminatedHelperParameterList);
                    }
                    else {
                        Context.Expect(')');

                        outputtedHeader = true;
                        Span headerSpan = HelperHeaderSpan.Create(Context, complete: !seenError, acceptedCharacters: AcceptedCharacters.Any);
                        End(headerSpan);
                        Context.FlushNextOutputSpan();

                        if (!HelperBodyParser(new CodeBlockInfo("Helper", block.Start, isTopLevel: true))) {
                            headerSpan.AutoCompleteString = VBCodeParser.EndHelperKeyword;
                        }
                    }
                }

                // Capture what we saw as an incomplete helper header span and return
                if (!outputtedHeader && readWhitespace) {
                    End(HelperHeaderSpan.Create(Context, complete: false));
                }

            }
            return true;
        }