|
@@ -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,
|