Bug 883333, part 7 - Refactor break and continue statement parsing. r=Waldo.

--HG--
extra : rebase_source : ec0914d23d10e5818fe1700e495c6c7e100ec72a
This commit is contained in:
Jason Orendorff 2013-06-21 08:17:59 -05:00
parent 5388c5e474
commit 0a0a0156eb
5 changed files with 102 additions and 83 deletions

View File

@ -250,12 +250,12 @@ class FullParseHandler
return new_<BinaryNode>(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body);
}
ParseNode *newContinue(PropertyName *label, uint32_t begin, uint32_t end) {
return new_<ContinueStatement>(label, begin, end);
ParseNode *newContinueStatement(PropertyName *label, const TokenPos &pos) {
return new_<ContinueStatement>(label, pos);
}
ParseNode *newBreak(PropertyName *label, uint32_t begin, uint32_t end) {
return new_<BreakStatement>(label, begin, end);
ParseNode *newBreakStatement(PropertyName *label, const TokenPos &pos) {
return new_<BreakStatement>(label, pos);
}
ParseNode *newReturnStatement(ParseNode *expr, const TokenPos &pos) {

View File

@ -1026,8 +1026,8 @@ class LabeledStatement : public ParseNode
class LoopControlStatement : public ParseNode
{
protected:
LoopControlStatement(ParseNodeKind kind, PropertyName *label, uint32_t begin, uint32_t end)
: ParseNode(kind, JSOP_NOP, PN_NULLARY, TokenPos::make(begin, end))
LoopControlStatement(ParseNodeKind kind, PropertyName *label, const TokenPos &pos)
: ParseNode(kind, JSOP_NOP, PN_NULLARY, pos)
{
JS_ASSERT(kind == PNK_BREAK || kind == PNK_CONTINUE);
pn_u.loopControl.label = label;
@ -1050,8 +1050,8 @@ class LoopControlStatement : public ParseNode
class BreakStatement : public LoopControlStatement
{
public:
BreakStatement(PropertyName *label, uint32_t begin, uint32_t end)
: LoopControlStatement(PNK_BREAK, label, begin, end)
BreakStatement(PropertyName *label, const TokenPos &pos)
: LoopControlStatement(PNK_BREAK, label, pos)
{ }
static bool test(const ParseNode &node) {
@ -1065,8 +1065,8 @@ class BreakStatement : public LoopControlStatement
class ContinueStatement : public LoopControlStatement
{
public:
ContinueStatement(PropertyName *label, uint32_t begin, uint32_t end)
: LoopControlStatement(PNK_CONTINUE, label, begin, end)
ContinueStatement(PropertyName *label, const TokenPos &pos)
: LoopControlStatement(PNK_CONTINUE, label, pos)
{ }
static bool test(const ParseNode &node) {

View File

@ -4315,6 +4315,90 @@ Parser<ParseHandler>::switchStatement()
return handler.newSwitchStatement(begin, discriminant, caseList);
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::continueStatement()
{
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_CONTINUE));
uint32_t begin = pos().begin;
RootedPropertyName label(context);
if (!MatchLabel(context, &tokenStream, &label))
return null();
StmtInfoPC *stmt = pc->topStmt;
if (label) {
for (StmtInfoPC *stmt2 = NULL; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
return null();
}
if (stmt->type == STMT_LABEL) {
if (stmt->label == label) {
if (!stmt2 || !stmt2->isLoop()) {
report(ParseError, false, null(), JSMSG_BAD_CONTINUE);
return null();
}
break;
}
} else {
stmt2 = stmt;
}
}
} else {
for (; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_BAD_CONTINUE);
return null();
}
if (stmt->isLoop())
break;
}
}
if (!MatchOrInsertSemicolon(context, &tokenStream))
return null();
return handler.newContinueStatement(label, TokenPos::make(begin, pos().end));
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::breakStatement()
{
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_BREAK));
uint32_t begin = pos().begin;
RootedPropertyName label(context);
if (!MatchLabel(context, &tokenStream, &label))
return null();
StmtInfoPC *stmt = pc->topStmt;
if (label) {
for (; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
return null();
}
if (stmt->type == STMT_LABEL && stmt->label == label)
break;
}
} else {
for (; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_TOUGH_BREAK);
return null();
}
if (stmt->isLoop() || stmt->type == STMT_SWITCH)
break;
}
}
if (!MatchOrInsertSemicolon(context, &tokenStream))
return null();
return handler.newBreakStatement(label, TokenPos::make(begin, pos().end));
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::returnOrYield(bool useAssignExpr)
@ -4735,78 +4819,11 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
case TOK_SWITCH:
return switchStatement();
case TOK_BREAK:
{
uint32_t begin = pos().begin;
RootedPropertyName label(context);
if (!MatchLabel(context, &tokenStream, &label))
return null();
pn = handler.newBreak(label, begin, pos().end);
if (!pn)
return null();
StmtInfoPC *stmt = pc->topStmt;
if (label) {
for (; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
return null();
}
if (stmt->type == STMT_LABEL && stmt->label == label)
break;
}
} else {
for (; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_TOUGH_BREAK);
return null();
}
if (stmt->isLoop() || stmt->type == STMT_SWITCH)
break;
}
}
break;
}
case TOK_CONTINUE:
{
uint32_t begin = pos().begin;
RootedPropertyName label(context);
if (!MatchLabel(context, &tokenStream, &label))
return null();
pn = handler.newContinue(label, begin, pos().end);
if (!pn)
return null();
StmtInfoPC *stmt = pc->topStmt;
if (label) {
for (StmtInfoPC *stmt2 = NULL; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_LABEL_NOT_FOUND);
return null();
}
if (stmt->type == STMT_LABEL) {
if (stmt->label == label) {
if (!stmt2 || !stmt2->isLoop()) {
report(ParseError, false, null(), JSMSG_BAD_CONTINUE);
return null();
}
break;
}
} else {
stmt2 = stmt;
}
}
} else {
for (; ; stmt = stmt->down) {
if (!stmt) {
report(ParseError, false, null(), JSMSG_BAD_CONTINUE);
return null();
}
if (stmt->isLoop())
break;
}
}
break;
}
return continueStatement();
case TOK_BREAK:
return breakStatement();
case TOK_RETURN:
pn = returnOrYield(false);

View File

@ -422,6 +422,8 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
Node whileStatement();
Node forStatement();
Node switchStatement();
Node continueStatement();
Node breakStatement();
Node withStatement();
Node labeledStatement();
Node tryStatement();

View File

@ -111,8 +111,8 @@ class SyntaxParseHandler
Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
Node newSwitchStatement(uint32_t begin, Node discriminant, Node caseList) { 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; }
Node newContinueStatement(PropertyName *label, const TokenPos &pos) { return NodeGeneric; }
Node newBreakStatement(PropertyName *label, const TokenPos &pos) { return NodeGeneric; }
Node newReturnStatement(Node expr, const TokenPos &pos) { return NodeGeneric; }
Node newLabeledStatement(PropertyName *label, Node stmt, uint32_t begin) {