diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2020-05-15 18:06:27 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-15 18:06:27 +0200 |
commit | 24275b26b82bf262dc48715ed5a3b11066f5dec4 (patch) | |
tree | b67c8c8b368bc907e00ae8ce3ec740329125a346 /modules/gdscript | |
parent | f06c44a02c2b643034babb8b90c89a4a22d0c62e (diff) | |
parent | c076a2b7e93b67d99a4b76462e4c4e1d92c738c5 (diff) |
Merge pull request #36726 from ThakeeNathees/invalid-break-parsing
Fix: break, continue outside of a loop, match statement handled when parsing
Diffstat (limited to 'modules/gdscript')
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 35 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.h | 2 |
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 |