summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_parser.cpp')
-rw-r--r--modules/gdscript/gdscript_parser.cpp26
1 files changed, 22 insertions, 4 deletions
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index a77fb14064..7f3dd6b2e5 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -130,8 +130,10 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags", { Variant::STRING, "names" }), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, 0, true);
register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_PHYSICS, Variant::INT>);
+ register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_NAVIGATION, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
+ register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
// Networking.
register_annotation(MethodInfo("@remote"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_REMOTE>);
register_annotation(MethodInfo("@master"), AnnotationInfo::VARIABLE | AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<MultiplayerAPI::RPC_MODE_MASTER>);
@@ -2080,6 +2082,17 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_unary_operator(ExpressionN
return operation;
}
+GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_not_in_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
+ // check that NOT is followed by IN by consuming it before calling parse_binary_operator which will only receive a plain IN
+ consume(GDScriptTokenizer::Token::IN, R"(Expected "in" after "not" in content-test operator.)");
+ ExpressionNode *in_operation = parse_binary_operator(p_previous_operand, p_can_assign);
+ UnaryOpNode *operation = alloc_node<UnaryOpNode>();
+ operation->operation = UnaryOpNode::OP_LOGIC_NOT;
+ operation->variant_op = Variant::OP_NOT;
+ operation->operand = in_operation;
+ return operation;
+}
+
GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
GDScriptTokenizer::Token op = previous;
BinaryOpNode *operation = alloc_node<BinaryOpNode>();
@@ -2906,7 +2919,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
// Logical
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_AND }, // AND,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_OR }, // OR,
- { &GDScriptParser::parse_unary_operator, nullptr, PREC_NONE }, // NOT,
+ { &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_not_in_operator, PREC_CONTENT_TEST }, // NOT,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_AND }, // AMPERSAND_AMPERSAND,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_LOGIC_OR }, // PIPE_PIPE,
{ &GDScriptParser::parse_unary_operator, nullptr, PREC_NONE }, // BANG,
@@ -3005,7 +3018,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
// Avoid desync.
static_assert(sizeof(rules) / sizeof(rules[0]) == GDScriptTokenizer::Token::TK_MAX, "Amount of parse rules don't match the amount of token types.");
- // Let's assume this this never invalid, since nothing generates a TK_MAX.
+ // Let's assume this is never invalid, since nothing generates a TK_MAX.
return &rules[p_token_type];
}
@@ -3157,11 +3170,16 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
push_error(R"(Cannot use "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation);
return false;
}
- if (variable->initializer->type != Node::LITERAL) {
+ if (variable->initializer->type == Node::LITERAL) {
+ variable->export_info.type = static_cast<LiteralNode *>(variable->initializer)->value.get_type();
+ } else if (variable->initializer->type == Node::ARRAY) {
+ variable->export_info.type = Variant::ARRAY;
+ } else if (variable->initializer->type == Node::DICTIONARY) {
+ variable->export_info.type = Variant::DICTIONARY;
+ } else {
push_error(R"(To use "@export" annotation with type-less variable, the default value must be a literal.)", p_annotation);
return false;
}
- variable->export_info.type = static_cast<LiteralNode *>(variable->initializer)->value.get_type();
} // else: Actual type will be set by the analyzer, which can infer the proper type.
}