/// <summary> /// Matches a <c>LastStatement</c> non-terminal. /// </summary> /// <returns><c>true</c> if the <c>LastStatement</c> was matched successfully; otherwise, <c>false</c>.</returns> /// <remarks> /// The non-terminal can start with: <c>Return</c>, <c>Break</c>. /// </remarks> protected virtual bool MatchLastStatement(BlockStatement block) { Statement statement = null; int start = this.LookAheadToken.StartOffset; if (!this.MatchLastStatementInner(out statement)) { statement = new IncompleteStatement( statement, new TextRange( start, this.Token.EndOffset ) ); } if ( statement != null ) { block.Statements.Add( statement ); } return true; }
/// <summary> /// Matches a <c>Block</c> non-terminal. /// </summary> /// <returns><c>true</c> if the <c>Block</c> was matched successfully; otherwise, <c>false</c>.</returns> /// <remarks> /// The non-terminal can start with: <c>Do</c>, <c>While</c>, <c>Repeat</c>, <c>If</c>, <c>For</c>, <c>Local</c>, <c>Function</c>, <c>Return</c>, <c>Break</c>, <c>OpenParenthesis</c>, <c>OpenCurlyBrace</c>, <c>Identifier</c>, <c>TripleDot</c>, <c>Nil</c>, <c>False</c>, <c>True</c>, <c>Number</c>, <c>Subtraction</c>, <c>Not</c>, <c>Hash</c>, <c>String</c>. /// </remarks> protected virtual bool MatchBlock(out BlockStatement block) { block = new BlockStatement(); block.StartOffset = this.LookAheadToken.StartOffset; if (this.IsInMultiMatchSet(0, this.LookAheadToken)) { this.MatchChunk(block); } block.EndOffset = this.LookAheadToken.StartOffset; return true; }
/// <summary> /// Matches a <c>Chunk</c> non-terminal. /// </summary> /// <returns><c>true</c> if the <c>Chunk</c> was matched successfully; otherwise, <c>false</c>.</returns> /// <remarks> /// The non-terminal can start with: <c>Do</c>, <c>While</c>, <c>Repeat</c>, <c>If</c>, <c>For</c>, <c>Local</c>, <c>Function</c>, <c>Return</c>, <c>Break</c>, <c>OpenParenthesis</c>, <c>OpenCurlyBrace</c>, <c>Identifier</c>, <c>TripleDot</c>, <c>Nil</c>, <c>False</c>, <c>True</c>, <c>Number</c>, <c>Subtraction</c>, <c>Not</c>, <c>Hash</c>, <c>String</c>. /// </remarks> protected virtual bool MatchChunk(BlockStatement block) { while (this.IsInMultiMatchSet(1, this.LookAheadToken)) { if (!this.MatchStatement(block)) return false; if (this.TokenIs(this.LookAheadToken, LuatTokenId.SemiColon)) { this.Match(LuatTokenId.SemiColon); } block.FirstUnconsumedToken = this.LookAheadToken; } if (((this.TokenIs(this.LookAheadToken, LuatTokenId.Return)) || (this.TokenIs(this.LookAheadToken, LuatTokenId.Break)))) { if (!this.MatchLastStatement(block)) return false; if (this.TokenIs(this.LookAheadToken, LuatTokenId.SemiColon)) { this.Match(LuatTokenId.SemiColon); } block.FirstUnconsumedToken = this.LookAheadToken; } return true; }
/// <summary> /// Matches a <c>CUBlock</c> non-terminal. /// </summary> /// <returns><c>true</c> if the <c>CUBlock</c> was matched successfully; otherwise, <c>false</c>.</returns> /// <remarks> /// The non-terminal can start with: <c>Do</c>, <c>While</c>, <c>Repeat</c>, <c>If</c>, <c>For</c>, <c>Local</c>, <c>Function</c>, <c>Return</c>, <c>Break</c>, <c>OpenParenthesis</c>, <c>OpenCurlyBrace</c>, <c>Identifier</c>, <c>TripleDot</c>, <c>Nil</c>, <c>False</c>, <c>True</c>, <c>Number</c>, <c>Subtraction</c>, <c>Not</c>, <c>Hash</c>, <c>String</c>. /// </remarks> protected virtual bool MatchCUBlock(out BlockStatement block) { block = new BlockStatement(); block.StartOffset = 0; while( !this.IsAtEnd ) { IToken prevToken = this.Token; bool bChunkError = true; int prevErrorCount = compilationUnit.SyntaxErrors.Count; if (this.MatchChunk(block)) { bChunkError = false; } // Did the Block non-terminal raise its own error message? bool bErrorsReported = compilationUnit.SyntaxErrors.Count > prevErrorCount; // Should we display an error for the text range of this block? bool bDisplayError = bChunkError && !bErrorsReported; if ( bDisplayError ) { int errorStart = ( block != null && block.FirstUnconsumedToken != null ) ? block.FirstUnconsumedToken.StartOffset : 0; int errorEnd = ( this.Token != null ) ? this.Token.EndOffset : this.LookAheadToken.EndOffset; this.ReportSyntaxError( new TextRange( errorStart, errorEnd ), "Invalid statement" ); } if ( this.Token == prevToken ) { // Token did not advance, probably due to error. // Move it along. this.AdvanceToNext(); } }; block.EndOffset = this.LookAheadToken.StartOffset; return true; }