diff options
Diffstat (limited to 'modules/gdscript/gdscript_parser.cpp')
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 109 |
1 files changed, 79 insertions, 30 deletions
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 7502f09d8a..2fa5084d84 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -32,14 +32,13 @@ #include "core/core_string_names.h" #include "core/engine.h" +#include "core/io/resource_loader.h" +#include "core/os/file_access.h" +#include "core/print_string.h" #include "core/project_settings.h" #include "core/reference.h" +#include "core/script_language.h" #include "gdscript.h" -#include "io/resource_loader.h" -#include "os/file_access.h" -#include "print_string.h" -#include "project_settings.h" -#include "script_language.h" template <class T> T *GDScriptParser::alloc_node() { @@ -82,8 +81,11 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { } tokenizer->advance(); - if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { + if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) { + return false; + } + if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { // be more python-like int current = tab_level.back()->get(); tab_level.push_back(current); @@ -93,10 +95,11 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { } while (true) { - if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { return false; //wtf + } else 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(); @@ -638,9 +641,21 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = op; } else { - - _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); - return NULL; + // Object is a special case + bool valid = false; + if (bi_type == Variant::OBJECT) { + int object_constant = ClassDB::get_integer_constant("Object", identifier, &valid); + if (valid) { + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value = object_constant; + cn->datatype = _type_from_variant(cn->value); + expr = cn; + } + } + if (!valid) { + _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); + return NULL; + } } } else { @@ -2479,7 +2494,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m Node *condition = NULL; - // chech for has, then for pattern + // check for has, then for pattern IdentifierNode *has = alloc_node<IdentifierNode>(); has->name = "has"; @@ -4383,10 +4398,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); } - if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVESYNC) { + if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE) { current_export = PropertyInfo(); - _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave', 'sync', 'remotesync', 'mastersync', 'slavesync'."); + _set_error("Expected 'var', 'onready', 'remote', 'master', 'puppet', 'sync', 'remotesync', 'mastersync', 'puppetsync'."); return; } @@ -4443,7 +4458,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { rpc_mode = MultiplayerAPI::RPC_MODE_MASTER; continue; } break; - case GDScriptTokenizer::TK_PR_SLAVE: { + case GDScriptTokenizer::TK_PR_SLAVE: +#ifdef DEBUG_ENABLED + _add_warning(GDScriptWarning::DEPRECATED_KEYWORD, tokenizer->get_token_line(), "slave", "puppet"); +#endif + case GDScriptTokenizer::TK_PR_PUPPET: { //may be fallthrough from export, ignore if so tokenizer->advance(); @@ -4460,7 +4479,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } - rpc_mode = MultiplayerAPI::RPC_MODE_SLAVE; + rpc_mode = MultiplayerAPI::RPC_MODE_PUPPET; continue; } break; case GDScriptTokenizer::TK_PR_REMOTESYNC: @@ -4476,7 +4495,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - rpc_mode = MultiplayerAPI::RPC_MODE_SYNC; + rpc_mode = MultiplayerAPI::RPC_MODE_REMOTESYNC; continue; } break; case GDScriptTokenizer::TK_PR_MASTERSYNC: { @@ -4494,7 +4513,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { rpc_mode = MultiplayerAPI::RPC_MODE_MASTERSYNC; continue; } break; - case GDScriptTokenizer::TK_PR_SLAVESYNC: { + case GDScriptTokenizer::TK_PR_PUPPETSYNC: { //may be fallthrough from export, ignore if so tokenizer->advance(); @@ -4506,7 +4525,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - rpc_mode = MultiplayerAPI::RPC_MODE_SLAVESYNC; + rpc_mode = MultiplayerAPI::RPC_MODE_PUPPETSYNC; continue; } break; case GDScriptTokenizer::TK_PR_VAR: { @@ -4536,14 +4555,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { member.rpc_mode = rpc_mode; if (current_class->constant_expressions.has(member.identifier)) { - _set_error("A constant named '" + String(member.identifier) + "' alread exists in this class (at line: " + + _set_error("A constant named '" + String(member.identifier) + "' already exists in this class (at line: " + itos(current_class->constant_expressions[member.identifier].expression->line) + ")."); return; } for (int i = 0; i < current_class->variables.size(); i++) { if (current_class->variables[i].identifier == member.identifier) { - _set_error("Variable '" + String(member.identifier) + "' alread exists in this class (at line: " + + _set_error("Variable '" + String(member.identifier) + "' already exists in this class (at line: " + itos(current_class->variables[i].line) + ")."); return; } @@ -4750,14 +4769,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { int line = tokenizer->get_token_line(); if (current_class->constant_expressions.has(const_id)) { - _set_error("Constant '" + String(const_id) + "' alread exists in this class (at line: " + + _set_error("Constant '" + String(const_id) + "' already exists in this class (at line: " + itos(current_class->constant_expressions[const_id].expression->line) + ")."); return; } for (int i = 0; i < current_class->variables.size(); i++) { if (current_class->variables[i].identifier == const_id) { - _set_error("A variable named '" + String(const_id) + "' alread exists in this class (at line: " + + _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " + itos(current_class->variables[i].line) + ")."); return; } @@ -4811,7 +4830,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { case GDScriptTokenizer::TK_PR_ENUM: { //multiple constant declarations.. - int last_assign = -1; // Incremented by 1 right before the assingment. + int last_assign = -1; // Incremented by 1 right before the assignment. String enum_name; Dictionary enum_dict; @@ -4848,6 +4867,20 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { StringName const_id = tokenizer->get_token_literal(); + if (current_class->constant_expressions.has(const_id)) { + _set_error("A constant named '" + String(const_id) + "' already exists in this class (at line: " + + itos(current_class->constant_expressions[const_id].expression->line) + ")."); + return; + } + + for (int i = 0; i < current_class->variables.size(); i++) { + if (current_class->variables[i].identifier == const_id) { + _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " + + itos(current_class->variables[i].line) + ")."); + return; + } + } + tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { @@ -5046,7 +5079,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) { if (found) continue; if (p->constant_expressions.has(base)) { - if (!p->constant_expressions[base].expression->type == Node::TYPE_CONSTANT) { + if (p->constant_expressions[base].expression->type != Node::TYPE_CONSTANT) { _set_error("Could not resolve constant '" + base + "'.", p_class->line); return; } @@ -5186,6 +5219,8 @@ String GDScriptParser::DataType::to_string() const { } return class_type->name.operator String(); } break; + case UNRESOLVED: { + } break; } return "Unresolved"; @@ -5758,7 +5793,10 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data expr_native = base->base_type.native_type; expr_script = base->base_type.script_type; } - } + } break; + case DataType::BUILTIN: // Already handled above + case DataType::UNRESOLVED: // Not allowed, see above + break; } switch (p_container.kind) { @@ -5801,7 +5839,10 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data expr_class = expr_class->base_type.class_type; } return false; - } + } break; + case DataType::BUILTIN: // Already handled above + case DataType::UNRESOLVED: // Not allowed, see above + break; } return false; @@ -6195,6 +6236,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { case Variant::COLOR: { error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::STRING; } break; + default: {} } } if (error) { @@ -6312,6 +6354,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } } } break; + default: {} } p_node->set_datatype(_resolve_type(node_type, p_node->line)); @@ -7201,6 +7244,12 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { expr.is_constant = true; c.type = expr; c.expression->set_datatype(expr); + + DataType tmp; + if (_get_member_type(p_class->base_type, E->key(), tmp)) { + _set_error("Member '" + String(E->key()) + "' already exists in parent class.", c.expression->line); + return; + } } // Function declarations @@ -7243,7 +7292,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { return; } - // Replace assigment with implict conversion + // Replace assignment with implict conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = v.line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7621,7 +7670,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { lv->line); return; } - // Replace assigment with implict conversion + // Replace assignment with implict conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = lv->line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7749,7 +7798,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { op->line); return; } - // Replace assigment with implict conversion + // Replace assignment with implict conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = op->line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7786,7 +7835,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { // Figure out function name for warning String func_name = _find_function_name(op); if (func_name.empty()) { - func_name == "<undetected name>"; + func_name = "<undetected name>"; } _add_warning(GDScriptWarning::RETURN_VALUE_DISCARDED, op->line, func_name); } |