wsgl parser: refactor statements()
Split out statments that are non-block (non-loops, etc) into a separate function. These all end with a semi-colon, which is important for resynchronization on errors (coming up in another change). Bug: tint:282 Change-Id: I0e58c4938f2bbe859dc6ffb8dcd45c8cf26101da Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32281 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
00bc8ba88c
commit
54af8746ae
|
@ -98,6 +98,52 @@ bool Statement::IsVariableDecl() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* Statement::Name() const {
|
||||||
|
if (IsAssign()) {
|
||||||
|
return "assignment statement";
|
||||||
|
}
|
||||||
|
if (IsBlock()) {
|
||||||
|
return "block statement";
|
||||||
|
}
|
||||||
|
if (IsBreak()) {
|
||||||
|
return "break statement";
|
||||||
|
}
|
||||||
|
if (IsCase()) {
|
||||||
|
return "case statement";
|
||||||
|
}
|
||||||
|
if (IsCall()) {
|
||||||
|
return "function call";
|
||||||
|
}
|
||||||
|
if (IsContinue()) {
|
||||||
|
return "continue statement";
|
||||||
|
}
|
||||||
|
if (IsDiscard()) {
|
||||||
|
return "discard statement";
|
||||||
|
}
|
||||||
|
if (IsElse()) {
|
||||||
|
return "else statement";
|
||||||
|
}
|
||||||
|
if (IsFallthrough()) {
|
||||||
|
return "fallthrough statement";
|
||||||
|
}
|
||||||
|
if (IsIf()) {
|
||||||
|
return "if statement";
|
||||||
|
}
|
||||||
|
if (IsLoop()) {
|
||||||
|
return "loop statement";
|
||||||
|
}
|
||||||
|
if (IsReturn()) {
|
||||||
|
return "return statement";
|
||||||
|
}
|
||||||
|
if (IsSwitch()) {
|
||||||
|
return "switch statement";
|
||||||
|
}
|
||||||
|
if (IsVariableDecl()) {
|
||||||
|
return "variable declaration";
|
||||||
|
}
|
||||||
|
return "statement";
|
||||||
|
}
|
||||||
|
|
||||||
const AssignmentStatement* Statement::AsAssign() const {
|
const AssignmentStatement* Statement::AsAssign() const {
|
||||||
assert(IsAssign());
|
assert(IsAssign());
|
||||||
return static_cast<const AssignmentStatement*>(this);
|
return static_cast<const AssignmentStatement*>(this);
|
||||||
|
|
|
@ -72,6 +72,9 @@ class Statement : public Node {
|
||||||
/// @returns true if this is an variable statement
|
/// @returns true if this is an variable statement
|
||||||
virtual bool IsVariableDecl() const;
|
virtual bool IsVariableDecl() const;
|
||||||
|
|
||||||
|
/// @returns the human readable name for the statement type.
|
||||||
|
const char* Name() const;
|
||||||
|
|
||||||
/// @returns the statement as a const assign statement
|
/// @returns the statement as a const assign statement
|
||||||
const AssignmentStatement* AsAssign() const;
|
const AssignmentStatement* AsAssign() const;
|
||||||
/// @returns the statement as a const block statement
|
/// @returns the statement as a const block statement
|
||||||
|
|
|
@ -1269,33 +1269,31 @@ Expect<std::unique_ptr<ast::BlockStatement>> ParserImpl::expect_statements() {
|
||||||
|
|
||||||
// statement
|
// statement
|
||||||
// : SEMICOLON
|
// : SEMICOLON
|
||||||
// | return_stmt SEMICOLON
|
// | body_stmt?
|
||||||
// | if_stmt
|
// | if_stmt
|
||||||
// | switch_stmt
|
// | switch_stmt
|
||||||
// | loop_stmt
|
// | loop_stmt
|
||||||
// | for_stmt
|
// | for_stmt
|
||||||
// | func_call_stmt SEMICOLON
|
// | non_block_statement
|
||||||
// | variable_stmt SEMICOLON
|
// : return_stmt SEMICOLON
|
||||||
// | break_stmt SEMICOLON
|
// | func_call_stmt SEMICOLON
|
||||||
// | continue_stmt SEMICOLON
|
// | variable_stmt SEMICOLON
|
||||||
// | DISCARD SEMICOLON
|
// | break_stmt SEMICOLON
|
||||||
// | assignment_stmt SEMICOLON
|
// | continue_stmt SEMICOLON
|
||||||
// | body_stmt?
|
// | DISCARD SEMICOLON
|
||||||
|
// | assignment_stmt SEMICOLON
|
||||||
Maybe<std::unique_ptr<ast::Statement>> ParserImpl::statement() {
|
Maybe<std::unique_ptr<ast::Statement>> ParserImpl::statement() {
|
||||||
while (match(Token::Type::kSemicolon)) {
|
while (match(Token::Type::kSemicolon)) {
|
||||||
// Skip empty statements
|
// Skip empty statements
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t = peek();
|
// Non-block statments all end in a semi-colon.
|
||||||
auto ret_stmt = return_stmt();
|
// TODO(bclayton): We can use this property to synchronize on error.
|
||||||
if (ret_stmt.errored)
|
auto stmt = non_block_statement();
|
||||||
|
if (stmt.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
if (ret_stmt.matched) {
|
if (stmt.matched)
|
||||||
if (!expect("return statement", Token::Type::kSemicolon))
|
return stmt;
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::move(ret_stmt.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto stmt_if = if_stmt();
|
auto stmt_if = if_stmt();
|
||||||
if (stmt_if.errored)
|
if (stmt_if.errored)
|
||||||
|
@ -1321,68 +1319,7 @@ Maybe<std::unique_ptr<ast::Statement>> ParserImpl::statement() {
|
||||||
if (stmt_for.matched)
|
if (stmt_for.matched)
|
||||||
return std::move(stmt_for.value);
|
return std::move(stmt_for.value);
|
||||||
|
|
||||||
auto func = func_call_stmt();
|
if (peek().IsBraceLeft()) {
|
||||||
if (func.errored)
|
|
||||||
return Failure::kErrored;
|
|
||||||
if (func.matched) {
|
|
||||||
if (!expect("function call", Token::Type::kSemicolon))
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::move(func.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto var = variable_stmt();
|
|
||||||
if (var.errored)
|
|
||||||
return Failure::kErrored;
|
|
||||||
if (var.matched) {
|
|
||||||
if (!expect("variable declaration", Token::Type::kSemicolon))
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::move(var.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto b = break_stmt();
|
|
||||||
if (b.errored)
|
|
||||||
return Failure::kErrored;
|
|
||||||
if (b.matched) {
|
|
||||||
if (!expect("break statement", Token::Type::kSemicolon))
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::move(b.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cont = continue_stmt();
|
|
||||||
if (cont.errored)
|
|
||||||
return Failure::kErrored;
|
|
||||||
if (cont.matched) {
|
|
||||||
if (!expect("continue statement", Token::Type::kSemicolon))
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::move(cont.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.IsDiscard()) {
|
|
||||||
auto source = t.source();
|
|
||||||
next(); // Consume the peek
|
|
||||||
|
|
||||||
if (!expect("discard statement", Token::Type::kSemicolon))
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::make_unique<ast::DiscardStatement>(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto assign = assignment_stmt();
|
|
||||||
if (assign.errored)
|
|
||||||
return Failure::kErrored;
|
|
||||||
if (assign.matched) {
|
|
||||||
if (!expect("assignment statement", Token::Type::kSemicolon))
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return std::move(assign.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
t = peek();
|
|
||||||
if (t.IsBraceLeft()) {
|
|
||||||
auto body = expect_body_stmt();
|
auto body = expect_body_stmt();
|
||||||
if (body.errored)
|
if (body.errored)
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
@ -1392,6 +1329,65 @@ Maybe<std::unique_ptr<ast::Statement>> ParserImpl::statement() {
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// statement (continued)
|
||||||
|
// : return_stmt SEMICOLON
|
||||||
|
// | func_call_stmt SEMICOLON
|
||||||
|
// | variable_stmt SEMICOLON
|
||||||
|
// | break_stmt SEMICOLON
|
||||||
|
// | continue_stmt SEMICOLON
|
||||||
|
// | DISCARD SEMICOLON
|
||||||
|
// | assignment_stmt SEMICOLON
|
||||||
|
Maybe<std::unique_ptr<ast::Statement>> ParserImpl::non_block_statement() {
|
||||||
|
auto stmt = [&]() -> Maybe<std::unique_ptr<ast::Statement>> {
|
||||||
|
auto ret_stmt = return_stmt();
|
||||||
|
if (ret_stmt.errored)
|
||||||
|
return Failure::kErrored;
|
||||||
|
if (ret_stmt.matched)
|
||||||
|
return std::move(ret_stmt.value);
|
||||||
|
|
||||||
|
auto func = func_call_stmt();
|
||||||
|
if (func.errored)
|
||||||
|
return Failure::kErrored;
|
||||||
|
if (func.matched)
|
||||||
|
return std::move(func.value);
|
||||||
|
|
||||||
|
auto var = variable_stmt();
|
||||||
|
if (var.errored)
|
||||||
|
return Failure::kErrored;
|
||||||
|
if (var.matched)
|
||||||
|
return std::move(var.value);
|
||||||
|
|
||||||
|
auto b = break_stmt();
|
||||||
|
if (b.errored)
|
||||||
|
return Failure::kErrored;
|
||||||
|
if (b.matched)
|
||||||
|
return std::move(b.value);
|
||||||
|
|
||||||
|
auto cont = continue_stmt();
|
||||||
|
if (cont.errored)
|
||||||
|
return Failure::kErrored;
|
||||||
|
if (cont.matched)
|
||||||
|
return std::move(cont.value);
|
||||||
|
|
||||||
|
auto assign = assignment_stmt();
|
||||||
|
if (assign.errored)
|
||||||
|
return Failure::kErrored;
|
||||||
|
if (assign.matched)
|
||||||
|
return std::move(assign.value);
|
||||||
|
|
||||||
|
Source source;
|
||||||
|
if (match(Token::Type::kDiscard, &source))
|
||||||
|
return std::make_unique<ast::DiscardStatement>(source);
|
||||||
|
|
||||||
|
return Failure::kNoMatch;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (stmt.matched && !expect(stmt->Name(), Token::Type::kSemicolon))
|
||||||
|
return Failure::kErrored;
|
||||||
|
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
// return_stmt
|
// return_stmt
|
||||||
// : RETURN logical_or_expression?
|
// : RETURN logical_or_expression?
|
||||||
Maybe<std::unique_ptr<ast::ReturnStatement>> ParserImpl::return_stmt() {
|
Maybe<std::unique_ptr<ast::ReturnStatement>> ParserImpl::return_stmt() {
|
||||||
|
|
|
@ -704,6 +704,7 @@ class ParserImpl {
|
||||||
|
|
||||||
Expect<ast::type::Type*> expect_type(const std::string& use);
|
Expect<ast::type::Type*> expect_type(const std::string& use);
|
||||||
|
|
||||||
|
Maybe<std::unique_ptr<ast::Statement>> non_block_statement();
|
||||||
Maybe<std::unique_ptr<ast::Statement>> for_header_initializer();
|
Maybe<std::unique_ptr<ast::Statement>> for_header_initializer();
|
||||||
Maybe<std::unique_ptr<ast::Statement>> for_header_continuing();
|
Maybe<std::unique_ptr<ast::Statement>> for_header_continuing();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue