mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 883333, part 7 - Refactor break and continue statement parsing. r=Waldo.
--HG-- extra : rebase_source : ec0914d23d10e5818fe1700e495c6c7e100ec72a
This commit is contained in:
parent
5388c5e474
commit
0a0a0156eb
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user