From d06ce2f11ec109f6568329438416a63fc09b96f2 Mon Sep 17 00:00:00 2001 From: George Marques Date: Mon, 17 Aug 2020 21:02:49 -0300 Subject: GDScript: Fix editor crash when writing @tool annotation --- modules/gdscript/gdscript_parser.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'modules/gdscript/gdscript_parser.cpp') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 0967f74285..d1ba8cd84d 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -494,16 +494,18 @@ void GDScriptParser::parse_program() { if (match(GDScriptTokenizer::Token::ANNOTATION)) { // Check for @tool annotation. AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::CLASS_LEVEL); - if (annotation->name == "@tool") { - // TODO: don't allow @tool anywhere else. (Should all script annotations be the first thing?). - _is_tool = true; - if (previous.type != GDScriptTokenizer::Token::NEWLINE) { - push_error(R"(Expected newline after "@tool" annotation.)"); - } - // @tool annotation has no specific target. - annotation->apply(this, nullptr); - } else { - annotation_stack.push_back(annotation); + if (annotation != nullptr) { + if (annotation->name == "@tool") { + // TODO: don't allow @tool anywhere else. (Should all script annotations be the first thing?). + _is_tool = true; + if (previous.type != GDScriptTokenizer::Token::NEWLINE) { + push_error(R"(Expected newline after "@tool" annotation.)"); + } + // @tool annotation has no specific target. + annotation->apply(this, nullptr); + } else { + annotation_stack.push_back(annotation); + } } } -- cgit v1.2.3 From 3abb3c0d6e9e81d3ed171162cc5ce2bbe58296e0 Mon Sep 17 00:00:00 2001 From: George Marques Date: Mon, 17 Aug 2020 21:30:39 -0300 Subject: GDScript: Fix crash when superclass file is non-existent Incidentally, allow EOF to be an end of statement. --- modules/gdscript/gdscript_parser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'modules/gdscript/gdscript_parser.cpp') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d1ba8cd84d..c9868cd80b 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -466,17 +466,17 @@ void GDScriptParser::pop_multiline() { } bool GDScriptParser::is_statement_end() { - return check(GDScriptTokenizer::Token::NEWLINE) || check(GDScriptTokenizer::Token::SEMICOLON); + return check(GDScriptTokenizer::Token::NEWLINE) || check(GDScriptTokenizer::Token::SEMICOLON) || check(GDScriptTokenizer::Token::TK_EOF); } void GDScriptParser::end_statement(const String &p_context) { bool found = false; - while (is_statement_end()) { + while (is_statement_end() && !is_at_end()) { // Remove sequential newlines/semicolons. found = true; advance(); } - if (!found) { + if (!found && !is_at_end()) { push_error(vformat(R"(Expected end of statement after %s, found "%s" instead.)", p_context, current.get_name())); } } -- cgit v1.2.3 From 0f9923e67f477ebab1fe903de53bf117ec3a886f Mon Sep 17 00:00:00 2001 From: George Marques Date: Mon, 17 Aug 2020 21:32:49 -0300 Subject: GDScript: Allow empty files to be valid scripts --- modules/gdscript/gdscript_parser.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'modules/gdscript/gdscript_parser.cpp') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index c9868cd80b..a0f37fcf23 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -482,12 +482,6 @@ void GDScriptParser::end_statement(const String &p_context) { } void GDScriptParser::parse_program() { - if (current.type == GDScriptTokenizer::Token::TK_EOF) { - // Empty file. - push_error("Source file is empty."); - return; - } - head = alloc_node(); current_class = head; -- cgit v1.2.3 From 35176247af80626684ff6bb1a1eb3bc031857b1c Mon Sep 17 00:00:00 2001 From: George Marques Date: Tue, 18 Aug 2020 17:44:20 -0300 Subject: GDScript: Allow enum values to be set to constant expressions Also allow them to access previous values wihout referencing the enum. --- modules/gdscript/gdscript_parser.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'modules/gdscript/gdscript_parser.cpp') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a0f37fcf23..e53a1090fe 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -1022,8 +1022,6 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { push_multiline(true); consume(GDScriptTokenizer::Token::BRACE_OPEN, vformat(R"(Expected "{" after %s.)", named ? "enum name" : R"("enum")")); - int current_value = 0; - do { if (check(GDScriptTokenizer::Token::BRACE_CLOSE)) { break; // Allow trailing comma. @@ -1031,6 +1029,9 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifer for enum key.)")) { EnumNode::Value item; item.identifier = parse_identifier(); + item.parent_enum = enum_node; + item.line = previous.start_line; + item.leftmost_column = previous.leftmost_column; if (!named) { // TODO: Abstract this recursive member check. @@ -1045,18 +1046,15 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { } if (match(GDScriptTokenizer::Token::EQUAL)) { - if (consume(GDScriptTokenizer::Token::LITERAL, R"(Expected integer value after "=".)")) { - item.custom_value = parse_literal(); - - if (item.custom_value->value.get_type() != Variant::INT) { - push_error(R"(Expected integer value after "=".)"); - item.custom_value = nullptr; - } else { - current_value = item.custom_value->value; - } + ExpressionNode *value = parse_expression(false); + if (value == nullptr) { + push_error(R"(Expected expression value after "=".)"); } + item.custom_value = value; } - item.value = current_value++; + item.rightmost_column = previous.rightmost_column; + + item.index = enum_node->values.size(); enum_node->values.push_back(item); if (!named) { // Add as member of current class. -- cgit v1.2.3