diff options
Diffstat (limited to 'modules/gdscript/gdscript_parser.cpp')
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index c059d8b2fa..9fb1030d12 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2042,7 +2042,37 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { push_error(R"(No pattern found for "match" branch.)"); } - if (!consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "match" patterns.)")) { + bool has_guard = false; + if (match(GDScriptTokenizer::Token::WHEN)) { + // Pattern guard. + // Create block for guard because it also needs to access the bound variables from patterns, and we don't want to add them to the outer scope. + branch->guard_body = alloc_node<SuiteNode>(); + if (branch->patterns.size() > 0) { + for (const KeyValue<StringName, IdentifierNode *> &E : branch->patterns[0]->binds) { + SuiteNode::Local local(E.value, current_function); + local.type = SuiteNode::Local::PATTERN_BIND; + branch->guard_body->add_local(local); + } + } + + SuiteNode *parent_block = current_suite; + branch->guard_body->parent_block = parent_block; + current_suite = branch->guard_body; + + ExpressionNode *guard = parse_expression(false); + if (guard == nullptr) { + push_error(R"(Expected expression for pattern guard after "when".)"); + } else { + branch->guard_body->statements.append(guard); + } + current_suite = parent_block; + complete_extents(branch->guard_body); + + has_guard = true; + branch->has_wildcard = false; // If it has a guard, the wildcard might still not match. + } + + if (!consume(GDScriptTokenizer::Token::COLON, vformat(R"(Expected ":"%s after "match" %s.)", has_guard ? "" : R"( or "when")", has_guard ? "pattern guard" : "patterns"))) { complete_extents(branch); return nullptr; } @@ -3681,6 +3711,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty { nullptr, nullptr, PREC_NONE }, // PASS, { nullptr, nullptr, PREC_NONE }, // RETURN, { nullptr, nullptr, PREC_NONE }, // MATCH, + { nullptr, nullptr, PREC_NONE }, // WHEN, // Keywords { nullptr, &GDScriptParser::parse_cast, PREC_CAST }, // AS, { nullptr, nullptr, PREC_NONE }, // ASSERT, |