Skip to content

Commit

Permalink
Fix parsing inner class declaration when "pass" keyword is on the sam…
Browse files Browse the repository at this point in the history
…e line

Implement a special case for allowing "pass" keyword in one-liner class
declaration, to be consistent with Python style.

```
class TestClass: pass
```

This commit fixes godotengine#56703
  • Loading branch information
kdiduk committed Jun 21, 2022
1 parent 3c35617 commit 5bcc3d4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 19 deletions.
78 changes: 59 additions & 19 deletions modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,51 @@ void GDScriptParser::_set_end_statement_error(String p_name) {
}

bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
if (!_parse_colon()) {
return false;
}

if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
// Be more Python-like.
IndentLevel current_level = indent_level.back()->get();
indent_level.push_back(current_level);
return true;
}

return _parse_indent_block_newlines(p_block);
}

bool GDScriptParser::_enter_inner_class_indent_block() {
if (!_parse_colon()) {
return false;
}

if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
// Check Python-like one-liner class declaration "class Foo: pass".
// Note: only "pass" is allowed on the same line after the colon.
if (tokenizer->get_token() != GDScriptTokenizer::TK_CF_PASS) {
return false;
}

GDScriptTokenizer::Token token = tokenizer->get_token(1);
if (token != GDScriptTokenizer::TK_NEWLINE && token != GDScriptTokenizer::TK_EOF) {
int line = tokenizer->get_token_line();
int col = tokenizer->get_token_column();
String message = "Invalid syntax: unexpected \"";
message += GDScriptTokenizer::get_token_name(token);
message += "\".";
_set_error(message, line, col);
return false;
}
return true;
}

return _parse_indent_block_newlines();
}

bool GDScriptParser::_parse_colon() {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COLON) {
// report location at the previous token (on the previous line)
// Report location at the previous token (on the previous line).
int error_line = tokenizer->get_token_line(-1);
int error_column = tokenizer->get_token_column(-1);
_set_error("':' expected at end of line.", error_line, error_column);
Expand All @@ -95,19 +138,12 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
return false;
}

if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
// be more python-like
IndentLevel current_level = indent_level.back()->get();
indent_level.push_back(current_level);
return true;
//_set_error("newline expected after ':'.");
//return false;
}
return true;
}

bool GDScriptParser::_parse_indent_block_newlines(BlockNode *p_block) {
while (true) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
return false; //wtf
} else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) {
if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) {
return false;
} else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) {
int indent = tokenizer->get_token_line_indent();
Expand All @@ -126,14 +162,13 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
indent_level.push_back(new_indent);
tokenizer->advance();
return true;

} else if (p_block) {
NewLineNode *nl = alloc_node<NewLineNode>();
nl->line = tokenizer->get_token_line();
p_block->statements.push_back(nl);
}

tokenizer->advance(); // go to next newline
tokenizer->advance(); // Go to the next newline.
}
}

Expand Down Expand Up @@ -3840,13 +3875,18 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}

if (!_enter_indent_block()) {
_set_error("Indented block expected.");
if (!_enter_inner_class_indent_block()) {
if (!error_set) {
_set_error("Indented block or \"pass\" expected.");
}
return;
}
current_class = newclass;
_parse_class(newclass);
current_class = p_class;

if (tokenizer->get_token() != GDScriptTokenizer::TK_CF_PASS) {
current_class = newclass;
_parse_class(newclass);
current_class = p_class;
}

} break;
/* this is for functions....
Expand Down
3 changes: 3 additions & 0 deletions modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,9 @@ class GDScriptParser {

bool _parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete = false, bool p_parsing_constant = false);
bool _enter_indent_block(BlockNode *p_block = nullptr);
bool _enter_inner_class_indent_block();
bool _parse_colon();
bool _parse_indent_block_newlines(BlockNode *p_block = nullptr);
bool _parse_newline();
Node *_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign = false, bool p_parsing_constant = false);
Node *_reduce_expression(Node *p_node, bool p_to_const = false);
Expand Down

0 comments on commit 5bcc3d4

Please sign in to comment.