--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -96,18 +96,20 @@ private:
bool parseExpression(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parsePropertyName(SimpleTokenReader* reader, UniquePtr<PropertyName>& out);
bool parseSwitchCaseList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseBlockStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
bool parseCatchClause(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
// --- Parse the contents of a node whose kind has already been determined.
- bool parseBlockStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
- bool parseExpressionStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+ bool parseBlockStatementAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+ bool parseExpressionStatementAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+ bool parseExpressionAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+ bool parseVariableDeclarationAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
// --- Utilities.
bool readString(SimpleTokenReader* reader, MutableHandleString);
const ReadOnlyCompileOptions& options() const;
ParseNodeAllocator allocator;
@@ -170,17 +172,17 @@ ASTReader::parseProgram(SimpleTokenReade
if (!reader->taggedTuple(&name, &fields, &sub)) {
return false;
}
if (name != "Program") {
return this->raiseError();
}
- return this->parseBlockStatementAux(&sub, &fields, out);
+ return this->parseBlockStatementAux(&sub, name, &fields, out);
}
bool
ASTReader::parseScope(SimpleTokenReader* reader,
ScopeData& out)
{
if (out.hasDirectEval.isSome()
|| out.letNames.address() != nullptr
@@ -236,16 +238,17 @@ ASTReader::parseScope(SimpleTokenReader*
|| out.capturedNames.address() == nullptr) {
return this->raiseError();
}
return true;
}
bool
ASTReader::parseBlockStatementAux(SimpleTokenReader* reader,
+ const std::string& name,
const SimpleTokenReader::Fields* fields,
UniquePtr<ParseNode>& out)
{
UniquePtr<ParseNode> body;
ScopeData scope(this->cx);
for (auto field: *fields) {
if (field == BINJS_SCOPE) {
@@ -385,23 +388,23 @@ ASTReader::parseStatement(SimpleTokenRea
if (name == "EmptyStatement") {
UniquePtr<ParseNode> result(new_<NullaryNode>(PNK_NOP, TokenPos()));
if (!result) {
return false;
}
out = Move(result);
} else if (name == "BlockStatement") {
UniquePtr<ParseNode> body;
- if (!this->parseBlockStatementAux(&sub, &fields, body)) {
+ if (!this->parseBlockStatementAux(&sub, name, &fields, body)) {
return false;
}
out = Move(body);
} else if (name == "ExpressionStatement") {
UniquePtr<ParseNode> body;
- if (!this->parseExpressionStatementAux(&sub, &fields, body)) {
+ if (!this->parseExpressionStatementAux(&sub, name, &fields, body)) {
return false;
}
out = Move(body);
} else if (name == "DebuggerStatement") {
UniquePtr<ParseNode> result(new_<DebuggerStatement>(TokenPos()));
if (!result) {
return false;
}
@@ -682,22 +685,135 @@ ASTReader::parseStatement(SimpleTokenRea
return false;
}
Unused << block.release();
Unused << handler.release();
Unused << finalizer.release();
out = Move(result);
- } else if (name == "WhileStatement") {
- // FIXME: Implement
- } else if (name == "DoWhileStatement") {
- // FIXME: Implement
+
+ } else if (name == "WhileStatement" || name == "DoWhileStatement") {
+
+ UniquePtr<ParseNode> test;
+ UniquePtr<ParseNode> body;
+
+ for (auto field: fields) {
+ if (field == "test") {
+ if (!this->parseExpression(&sub, test)) {
+ return false;
+ }
+ } else if (field == "body") {
+ if (!this->parseStatement(&sub, test)) {
+ return false;
+ }
+ } else {
+ return this->raiseError();
+ }
+ }
+
+ if (!test || !body) {
+ return this->raiseError();
+ }
+
+ if (name == "WhileStatement") {
+ UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_WHILE, JSOP_NOP, TokenPos(), body.get(), test.get()));
+
+ if (!result) {
+ return false;
+ }
+ out = Move(result);
+ } else {
+ UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, TokenPos(), body.get(), test.get()));
+
+ if (!result) {
+ return false;
+ }
+ out = Move(result);
+ }
+
+ Unused << test.release();
+ Unused << body.release();
+
} else if (name == "ForStatement") {
- // FIXME: Implement
+
+ UniquePtr<ParseNode> init; // Optional
+ UniquePtr<ParseNode> test; // Optional
+ UniquePtr<ParseNode> update; // Optional
+ ScopeData scope(this->cx); // Optional
+ UniquePtr<ParseNode> body; // Required
+
+ for (auto field: fields) {
+ if (field == "init") {
+
+ // This can be either a VarDecl or an Expression.
+ SimpleTokenReader::Fields subFields(this->cx);
+ SimpleTokenReader subSub(this->cx);
+ std::string subName;
+
+ if (!sub.taggedTuple(&subName, &subFields, &subSub)) {
+ return false;
+ }
+
+
+ if (subName == "VariableDeclaration") {
+ if (!this->parseVariableDeclarationAux(&subSub, subName, &subFields, init)) {
+ return false;
+ }
+ } else /* Parse as expression */ {
+ if (!this->parseExpressionAux(&subSub, subName, &subFields, init)) {
+ return false;
+ }
+ }
+
+ } else if (field == "test") {
+ if (!this->parseExpression(&sub, test)) {
+ return false;
+ }
+ } else if (field == "update") {
+ if (!this->parseExpression(&sub, update)) {
+ return false;
+ }
+ } else if (field == BINJS_SCOPE) {
+ if (!this->parseScope(&sub, scope)) {
+ return false;
+ }
+ } else if (field == "body") {
+ if (!this->parseStatement(&sub, body)) {
+ return false;
+ }
+ } else {
+ return this->raiseError();
+ }
+ }
+
+ if (!body) {
+ return this->raiseError();
+ }
+
+ UniquePtr<ParseNode> forHead(new_<TernaryNode>(PNK_FORHEAD, JSOP_NOP, init.get(), test.get(), update.get(), TokenPos()));
+ if (!forHead) {
+ return false;
+ }
+ Unused << init.release();
+ Unused << update.release();
+ Unused << test.release();
+
+ UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_FOR, JSOP_NOP, TokenPos(),
+ forHead.get(), body.get()));
+
+ if (!result) {
+ return false;
+ }
+
+ Unused << forHead.release();
+ Unused << body.release();
+
+ out = Move(result);
+
} else if (name == "ForInStatement") {
// FIXME: Implement
} else if (name == "FunctionDeclaration") {
// FIXME: Implement
} else if (name == "VariableDeclaration") {
// FIXME: Implement
} else if (name == "SwitchStatement") {
// FIXME: Implement