summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/gdscript/gdscript_parser.cpp35
-rw-r--r--modules/gdscript/gdscript_parser.h2
2 files changed, 37 insertions, 0 deletions
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 57531ed13b..fbb5f91139 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3151,6 +3151,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
cf_while->body = alloc_node<BlockNode>();
cf_while->body->parent_block = p_block;
+ cf_while->body->can_break = true;
+ cf_while->body->can_continue = true;
p_block->sub_blocks.push_back(cf_while->body);
if (!_enter_indent_block(cf_while->body)) {
@@ -3278,6 +3280,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
cf_for->body = alloc_node<BlockNode>();
cf_for->body->parent_block = p_block;
+ cf_for->body->can_break = true;
+ cf_for->body->can_continue = true;
p_block->sub_blocks.push_back(cf_for->body);
if (!_enter_indent_block(cf_for->body)) {
@@ -3308,6 +3312,21 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->statements.push_back(cf_for);
} break;
case GDScriptTokenizer::TK_CF_CONTINUE: {
+ BlockNode *upper_block = p_block;
+ bool is_continue_valid = false;
+ while (upper_block) {
+ if (upper_block->can_continue) {
+ is_continue_valid = true;
+ break;
+ }
+ upper_block = upper_block->parent_block;
+ }
+
+ if (!is_continue_valid) {
+ _set_error("Unexpected keyword \"continue\" outside a loop.");
+ return;
+ }
+
_mark_line_as_safe(tokenizer->get_token_line());
tokenizer->advance();
ControlFlowNode *cf_continue = alloc_node<ControlFlowNode>();
@@ -3319,6 +3338,21 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
}
} break;
case GDScriptTokenizer::TK_CF_BREAK: {
+ BlockNode *upper_block = p_block;
+ bool is_break_valid = false;
+ while (upper_block) {
+ if (upper_block->can_break) {
+ is_break_valid = true;
+ break;
+ }
+ upper_block = upper_block->parent_block;
+ }
+
+ if (!is_break_valid) {
+ _set_error("Unexpected keyword \"break\" outside a loop.");
+ return;
+ }
+
_mark_line_as_safe(tokenizer->get_token_line());
tokenizer->advance();
ControlFlowNode *cf_break = alloc_node<ControlFlowNode>();
@@ -3384,6 +3418,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
BlockNode *compiled_branches = alloc_node<BlockNode>();
compiled_branches->parent_block = p_block;
compiled_branches->parent_class = p_block->parent_class;
+ compiled_branches->can_continue = true;
p_block->sub_blocks.push_back(compiled_branches);
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index cfcca9584e..7dedb6d6f9 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -231,6 +231,8 @@ public:
List<Node *> statements;
Map<StringName, LocalVarNode *> variables;
bool has_return = false;
+ bool can_break = false;
+ bool can_continue = false;
Node *if_condition = nullptr; //tiny hack to improve code completion on if () blocks