Bug 883333, part 4 - Refactor while and do-while statement parsing. r=Waldo.

--HG--
extra : rebase_source : 26dd5b2425fdc9216c47d679877490f8d1432bd4
This commit is contained in:
Jason Orendorff 2013-06-21 08:17:58 -05:00
parent 8ff3023e61
commit c07de1c091
4 changed files with 69 additions and 50 deletions

View File

@ -209,6 +209,15 @@ class FullParseHandler
return pn;
}
ParseNode *newDoWhileStatement(ParseNode *body, ParseNode *cond, const TokenPos &pos) {
return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond);
}
ParseNode *newWhileStatement(uint32_t begin, ParseNode *cond, ParseNode *body) {
TokenPos pos = TokenPos::make(begin, body->pn_pos.end);
return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
}
ParseNode *newCaseOrDefault(uint32_t begin, ParseNode *expr, ParseNode *body) {
TokenPos pos = TokenPos::make(begin, body->pn_pos.end);
return new_<BinaryNode>(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body);

View File

@ -3652,6 +3652,56 @@ Parser<ParseHandler>::ifStatement()
return handler.newIfStatement(begin, cond, thenBranch, elseBranch);
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::doWhileStatement()
{
uint32_t begin = pos().begin;
StmtInfoPC stmtInfo(context);
PushStatementPC(pc, &stmtInfo, STMT_DO_LOOP);
Node body = statement();
if (!body)
return null();
MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO);
Node cond = condition();
if (!cond)
return null();
PopStatementPC(context, pc);
if (versionNumber() == JSVERSION_ECMA_3) {
// Pedantically require a semicolon or line break, following ES3.
// Bug 880329 proposes removing this case.
if (!MatchOrInsertSemicolon(context, &tokenStream))
return null();
} else {
// The semicolon after do-while is even more optional than most
// semicolons in JS. Web compat required this by 2004:
// http://bugzilla.mozilla.org/show_bug.cgi?id=238945
// ES3 and ES5 disagreed, but ES6 conforms to Web reality:
// https://bugs.ecmascript.org/show_bug.cgi?id=157
(void) tokenStream.matchToken(TOK_SEMI);
}
return handler.newDoWhileStatement(body, cond, TokenPos::make(begin, pos().end));
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::whileStatement()
{
uint32_t begin = pos().begin;
StmtInfoPC stmtInfo(context);
PushStatementPC(pc, &stmtInfo, STMT_WHILE_LOOP);
Node cond = condition();
if (!cond)
return null();
Node body = statement();
if (!body)
return null();
PopStatementPC(context, pc);
return handler.newWhileStatement(begin, cond, body);
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::matchInOrOf(bool *isForOfp)
@ -4686,62 +4736,18 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
case TOK_IF:
return ifStatement();
case TOK_SWITCH:
return switchStatement();
case TOK_DO:
return doWhileStatement();
case TOK_WHILE:
{
uint32_t begin = pos().begin;
StmtInfoPC stmtInfo(context);
PushStatementPC(pc, &stmtInfo, STMT_WHILE_LOOP);
Node cond = condition();
if (!cond)
return null();
Node body = statement();
if (!body)
return null();
PopStatementPC(context, pc);
pn = handler.newBinary(PNK_WHILE, cond, body);
if (!pn)
return null();
handler.setBeginPosition(pn, begin);
return pn;
}
case TOK_DO:
{
uint32_t begin = pos().begin;
StmtInfoPC stmtInfo(context);
PushStatementPC(pc, &stmtInfo, STMT_DO_LOOP);
Node body = statement();
if (!body)
return null();
MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO);
Node cond = condition();
if (!cond)
return null();
PopStatementPC(context, pc);
pn = handler.newBinary(PNK_DOWHILE, body, cond);
if (!pn)
return null();
handler.setBeginPosition(pn, begin);
if (versionNumber() != JSVERSION_ECMA_3) {
/*
* All legacy and extended versions must do automatic semicolon
* insertion after do-while. See the testcase and discussion in
* http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
*/
(void) tokenStream.matchToken(TOK_SEMI);
return pn;
}
break;
}
return whileStatement();
case TOK_FOR:
return forStatement();
case TOK_SWITCH:
return switchStatement();
case TOK_BREAK:
{
uint32_t begin = pos().begin;

View File

@ -418,6 +418,8 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
Node statements();
Node ifStatement();
Node doWhileStatement();
Node whileStatement();
Node forStatement();
Node switchStatement();
Node withStatement();

View File

@ -107,6 +107,8 @@ class SyntaxParseHandler
}
Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; }
Node newDoWhileStatement(Node body, Node cond, const TokenPos &pos) { return NodeGeneric; }
Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
Node newContinue(PropertyName *label, uint32_t begin, uint32_t end) { return NodeGeneric; }
Node newBreak(PropertyName *label, uint32_t begin, uint32_t end) { return NodeGeneric; }