/// <summary> /// Parses a block of statements. /// </summary> /// <returns> A BlockStatement containing the statements. </returns> /// <remarks> The value of a block statement is the value of the last statement in the block, /// or undefined if there are no statements in the block. </remarks> private BlockStatement ParseBlock() { // Consume the start brace ({). this.Expect(PunctuatorToken.LeftBrace); // Read zero or more statements. var result = new BlockStatement(this.labelsForCurrentStatement); while (true) { // Check for the end brace (}). if (this.nextToken == PunctuatorToken.RightBrace) break; // Parse a single statement. result.Statements.Add(ParseStatement()); } // Consume the end brace. this.Expect(PunctuatorToken.RightBrace); return result; }
// PARSE METHODS //_________________________________________________________________________________________ /// <summary> /// Parses javascript source code. /// </summary> /// <returns> An expression that can be executed to run the program represented by the /// source code. </returns> public Statement Parse() { // Read the directive prologue. var result = new BlockStatement(new string[0]); while (true) { // Check if we should stop parsing. if (this.nextToken == this.endToken) break; // A directive must start with a string literal token. Record it now so that the // escape sequence and line continuation information is not lost. var directiveToken = this.nextToken as StringLiteralToken; if (directiveToken == null) break; // Directives cannot have escape sequences or line continuations. if (directiveToken.EscapeSequenceCount != 0 || directiveToken.LineContinuationCount != 0) break; // If the statement starts with a string literal, it must be an expression. var beforeInitialToken = this.PositionAfterWhitespace; var expression = ParseExpression(PunctuatorToken.Semicolon); // The statement must be added to the AST so that eval("'test'") works. var initialStatement = new ExpressionStatement(this.labelsForCurrentStatement, expression); initialStatement.SourceSpan = new SourceCodeSpan(beforeInitialToken, this.PositionBeforeWhitespace); result.Statements.Add(initialStatement); // In order for the expression to be part of the directive prologue, it must // consist solely of a string literal. if ((expression is LiteralExpression) == false) break; // Strict mode directive. if (directiveToken.Value == "use strict") this.StrictMode = true; // Read the end of the statement. This must happen last so that the lexer has a // chance to act on the strict mode flag. ExpectEndOfStatement(); } // Call the directive prologue callback. if (this.DirectivePrologueProcessedCallback != null) this.DirectivePrologueProcessedCallback(this); // Read zero or more regular statements. while (true) { // Check if we should stop parsing. if (this.nextToken == this.endToken) break; // Parse a single statement. result.Statements.Add(ParseStatement()); } return result; }