예제 #1
0
	// Parse a statement.
	private JNode Statement()
			{
				JNode stmt = null;
				JNode temp, temp2;
				Context save;

				// Save the current context, so that we know
				// where the statement starts.
				save = tokenInfo.MakeCopy();

				// Determine what kind of statement to parse.
				switch(token)
				{
					case JSToken.LeftCurly:
					{
						// Compound statement encountered.
						NextToken();
						while(token != JSToken.RightCurly &&
							  token != JSToken.EndOfFile)
						{
							temp = Statement();
							stmt = Support.CreateCompound(stmt, temp);
						}
						if(stmt == null)
						{
							stmt = new JEmpty(Context.BuildRange
												(save, tokenInfo));
						}
						else if(stmt is JCompound)
						{
							// Make sure the compound statement includes
							// the curly brackets.
							stmt.context = Context.BuildRange
												(save, tokenInfo);
						}
						if(token == JSToken.EndOfFile)
						{
							SyntaxError("`}' expected");
						}
						else
						{
							NextToken();
						}
					}
					break;

					case JSToken.Semicolon:
					{
						// Bare semi-colon for an empty statement.
						stmt = new JEmpty(save);
						NextToken();
					}
					break;

					case JSToken.If:
					{
						// Parse an "if" statement.
						NextToken();
						temp = BracketedExpression();
						stmt = Statement();
						if(token != JSToken.Else)
						{
							stmt = new JIf(Context.BuildRange
												(save, stmt.context),
										   temp, stmt, null);
						}
						else
						{
							NextToken();
							temp2 = Statement();
							stmt = new JIf(Context.BuildRange
												(save, temp2.context),
										   temp, stmt, temp2);
						}
					}
					break;

					case JSToken.While:
					{
						// Parse a "while" statement.
						NextToken();
						temp = BracketedExpression();
						stmt = Statement();
						stmt = new JWhile(Context.BuildRange
											(save, stmt.context),
										  temp, stmt);
					}
					break;

					case JSToken.Do:
					{
						// Parse a "do" statement.
						NextToken();
						stmt = Statement();
						Expect(JSToken.While, "`while' expected");
						temp = BracketedExpression();
						stmt = new JDo(Context.BuildRange(save, temp.context),
									   stmt, temp);
					}
					break;

					case JSToken.Continue:
					{
						// Parse a "continue" statement.
						NextToken();
						if(HaveSemiColon())
						{
							// Continue with no label.
							stmt = new JContinue(save, null);
							MatchSemiColon();
						}
						else if(token == JSToken.Identifier)
						{
							// Extract the label.
							stmt = new JContinue
								(Context.BuildRange(save, tokenInfo),
								 scanner.GetIdentifierName());
							NextToken();
							MatchSemiColon();
						}
						else
						{
							SyntaxError("`continue' label expected");
						}
					}
					break;

					case JSToken.Break:
					{
						// Parse a "break" statement.
						NextToken();
						if(HaveSemiColon())
						{
							// Break with no label.
							stmt = new JBreak(save, null);
							MatchSemiColon();
						}
						else if(token == JSToken.Identifier)
						{
							// Extract the label.
							stmt = new JBreak
								(Context.BuildRange(save, tokenInfo),
								 scanner.GetIdentifierName());
							NextToken();
							MatchSemiColon();
						}
						else
						{
							SyntaxError("`break' label expected");
						}
					}
					break;

					case JSToken.Return:
					{
						// Parse a "return" statement.
						NextToken();
						if(HaveSemiColon())
						{
							// Return with no expression.
							stmt = new JReturn(save);
							MatchSemiColon();
						}
						else
						{
							// Return with an expression.
							temp = Expression();
							stmt = new JReturnExpr
								(Context.BuildRange(save, temp.context), temp);
							MatchSemiColon();
						}
					}
					break;

					case JSToken.Throw:
					{
						// Parse a "throw" statement.
						NextToken();
						if(HaveSemiColon())
						{
							// Throw with missing expression.
							SyntaxError("expression expected");
						}
						else
						{
							// Parse the expression for the "throw".
							temp = Expression();
							stmt = new JThrow
								(Context.BuildRange(save, temp.context), temp);
							MatchSemiColon();
						}
					}
					break;

					case JSToken.With:
					{
						// Parse a "with" statement.
						NextToken();
						temp = BracketedExpression();
						stmt = Statement();
						stmt = new JWith(Context.BuildRange(save, stmt.context),
										 temp, stmt);
					}
					break;

					case JSToken.Var:
					{
						// Parse a variable declaration.
						NextToken();
						stmt = VariableDeclarationList(false);
						MatchSemiColon();
					}
					break;

					case JSToken.For:
					{
						// Parse a "for" statement.
						JNode init, cond, incr;
						NextToken();
						Expect(JSToken.LeftParen, "`(' expected");

						// Parse the initialization expression.
						if(token == JSToken.Var)
						{
							// Starts with a variable declaration.
							NextToken();
							init = VariableDeclarationList(true);
						}
						else if(token == JSToken.Semicolon)
						{
							// No initialization expression.
							init = null;
						}
						else
						{
							// No variable declarations.
							init = ExpressionNoIn();
							init = new JExprStmt
								(init.context.MakeCopy(), init);
						}

						// Is this the normal or "in" form?
						if(token != JSToken.In)
						{
							Expect(JSToken.Semicolon, "`;' expected");
							if(token != JSToken.Semicolon)
							{
								cond = Expression();
							}
							else
							{
								cond = null;
							}
							Expect(JSToken.Semicolon, "`;' expected");
							if(token != JSToken.RightParen)
							{
								incr = Expression();
							}
							else
							{
								incr = null;
							}
							Expect(JSToken.RightParen, "`)' expected");
							temp = Statement();
							stmt = new JFor(Context.BuildRange
												(save, temp.context),
											init, cond, incr, temp);
						}
						else
						{
							if(init is JCompound)
							{
								SyntaxError("only one variable name can be " +
											"used with for(var ... in ...)");
							}
							else if(init != null && !(init is JVarDecl))
							{
								CheckLeftHandSideExpression(init);
							}
							NextToken();
							cond = Expression();
							Expect(JSToken.RightParen, "`)' expected");
							temp = Statement();
							stmt = new JForIn(Context.BuildRange
												(save, temp.context),
											  init, cond, temp);
						}

					}
					break;

					case JSToken.Switch:
					{
						// Parse a "switch" statement.
						NextToken();
						temp = BracketedExpression();
						Expect(JSToken.LeftCurly, "`{' expected");
						stmt = CaseBlock();
						Expect(JSToken.RightCurly, "`}' expected");
						if(stmt != null)
						{
							stmt = new JSwitch(Context.BuildRange
													(save, stmt.context),
											   temp, stmt);
						}
						else
						{
							// No clauses, so evaluate the expression
							// for its side-effects only.
							stmt = new JExprStmt
								(temp.context.MakeCopy(), temp);
						}
					}
					break;

					case JSToken.Try:
					{
						// Parse a "try" statement.
						String catchName = null;
						JNode catchClause = null;
						JNode finallyClause = null;
						NextToken();
						stmt = Block();
						if(token == JSToken.Catch)
						{
							NextToken();
							Expect(JSToken.LeftParen, "`(' expected");
							if(token != JSToken.Identifier)
							{
								SyntaxError("identifier expected");
							}
							catchName = scanner.GetIdentifierName();
							NextToken();
							Expect(JSToken.RightParen, "`)' expected");
							catchClause = Block();
						}
						else if(token != JSToken.Finally)
						{
							SyntaxError("`catch' or `finally' expected");
						}
						if(token == JSToken.Finally)
						{
							NextToken();
							finallyClause = Block();
							save = Context.BuildRange
								(save, finallyClause.context);
						}
						else
						{
							save = Context.BuildRange
								(save, catchClause.context);
						}
						stmt = new JTry(save, stmt, catchName,
										catchClause, finallyClause);
					}
					break;

					default:
					{
						// Should be an expression.
						temp = StatementExpression();
						if(token == JSToken.Colon)
						{
							// The expression is followed by a colon,
							// so it is probably a label.
							if(!(temp is JIdentifier))
							{
								SyntaxError("invalid statement label");
							}
							NextToken();
							stmt = Statement();
							Support.AddLabel
								(((JIdentifier)temp).name, stmt);
							stmt.context = Context.BuildRange
								(save, stmt.context);
						}
						else
						{
							// Ordinary expression statement.
							stmt = new JExprStmt
								(Context.BuildRange(save, temp.context), temp);
							MatchSemiColon();
						}
					}
					break;
				}

				// Return the statement to the caller.
				return stmt;
			}
예제 #2
0
	// Parse a list of statements within a "switch" case block.
	private JNode CaseStatementList()
			{
				JNode stmt = null;
				JNode stmt2;
				while(token != JSToken.RightCurly &&
					  token != JSToken.Case &&
					  token != JSToken.Default)
				{
					stmt2 = Statement();
					stmt = Support.CreateCompound(stmt, stmt2);
				}
				if(stmt == null)
				{
					stmt = new JEmpty(tokenInfo.MakeCopy());
				}
				return stmt;
			}