fune/js/src/frontend/ParseContext-inl.h
David Teller b6e2e4872e Bug 1377007 - Implementing basic binjs-ref parser in SpiderMonkey;r=arai,jorendorff
This patch implements a Binary AST parser matching the latest
binjs-ref parser at this date. The subset of JS recognized matches
ES5, with an AST based on a slightly customized Babylon AST.

At this stage, the parser trusts its input, insofar as it does not
check directives or bindings. Followup patch will introduce checking
of these directives/bindings.

MozReview-Commit-ID: 1nt230rt02R

--HG--
extra : rebase_source : 1500f15c296342dcacd65d9ab12800bdea3a1258
2017-09-11 16:54:48 +02:00

96 lines
2.9 KiB
C++

#ifndef frontend_ParseContext_inl_h
#define frontend_ParseContext_inl_h
#include "frontend/ParseContext.h"
namespace js {
namespace frontend {
template <>
inline bool
ParseContext::Statement::is<ParseContext::LabelStatement>() const
{
return kind_ == StatementKind::Label;
}
template <>
inline bool
ParseContext::Statement::is<ParseContext::ClassStatement>() const
{
return kind_ == StatementKind::Class;
}
inline JS::Result<Ok, ParseContext::BreakStatementError>
ParseContext::checkBreakStatement(PropertyName* label)
{
// Labeled 'break' statements target the nearest labeled statements (could
// be any kind) with the same label. Unlabeled 'break' statements target
// the innermost loop or switch statement.
if (label) {
auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
MOZ_ASSERT(stmt);
return stmt->label() == label;
};
if (!findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel))
return mozilla::Err(ParseContext::BreakStatementError::LabelNotFound);
} else {
auto isBreakTarget = [](ParseContext::Statement* stmt) {
return StatementKindIsUnlabeledBreakTarget(stmt->kind());
};
if (!findInnermostStatement(isBreakTarget))
return mozilla::Err(ParseContext::BreakStatementError::ToughBreak);
}
return Ok();
}
inline JS::Result<Ok, ParseContext::ContinueStatementError>
ParseContext::checkContinueStatement(PropertyName* label)
{
// Labeled 'continue' statements target the nearest labeled loop
// statements with the same label. Unlabeled 'continue' statements target
// the innermost loop statement.
auto isLoop = [](ParseContext::Statement* stmt) {
MOZ_ASSERT(stmt);
return StatementKindIsLoop(stmt->kind());
};
if (!label) {
// Unlabeled statement: we target the innermost loop, so make sure that
// there is an innermost loop.
if (!findInnermostStatement(isLoop))
return mozilla::Err(ParseContext::ContinueStatementError::NotInALoop);
return Ok();
}
// Labeled statement: targest the nearest labeled loop with the same label.
ParseContext::Statement* stmt = innermostStatement();
bool foundLoop = false; // True if we have encountered at least one loop.
for (;;) {
stmt = ParseContext::Statement::findNearest(stmt, isLoop);
if (!stmt)
return foundLoop ? mozilla::Err(ParseContext::ContinueStatementError::LabelNotFound)
: mozilla::Err(ParseContext::ContinueStatementError::NotInALoop);
foundLoop = true;
// Is it labeled by our label?
stmt = stmt->enclosing();
while (stmt && stmt->is<ParseContext::LabelStatement>()) {
if (stmt->as<ParseContext::LabelStatement>().label() == label)
return Ok();
stmt = stmt->enclosing();
}
}
}
}
}
#endif // frontend_ParseContext_inl_h