diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 8457a090559..4eaf7fcb55b 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -5196,7 +5196,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc return an; } -ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info) { +ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info, const ExpressionInfo *p_previous_expression_info) { Vector expression; //Vector operators; @@ -6551,6 +6551,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons pos = _get_tkpos(); tk = _get_token(); + if (p_previous_expression_info != nullptr && tk.type == p_previous_expression_info->tt_break && !p_previous_expression_info->is_last_expr) { + break; + } + if (is_token_operator(tk.type)) { Expression o; o.is_op = true; @@ -6657,6 +6661,31 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(o); + if (o.op == OP_SELECT_IF) { + ExpressionInfo info; + info.expression = &expression; + info.tt_break = TK_COLON; + + expr = _parse_and_reduce_expression(p_block, p_function_info, &info); + if (!expr) { + return nullptr; + } + + expression.push_back({ true, { OP_SELECT_ELSE } }); + + if (p_previous_expression_info != nullptr) { + info.is_last_expr = p_previous_expression_info->is_last_expr; + } else { + info.is_last_expr = true; + } + + expr = _parse_and_reduce_expression(p_block, p_function_info, &info); + if (!expr) { + return nullptr; + } + + break; + } } else { _set_tkpos(pos); //something else, so rollback and end break; @@ -6969,6 +6998,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } + if (p_previous_expression_info != nullptr) { + p_previous_expression_info->expression->push_back(expression[0]); + } + return expression[0].node; } @@ -7081,8 +7114,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha return p_node; } -ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info) { - ShaderLanguage::Node *expr = _parse_expression(p_block, p_function_info); +ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info, const ExpressionInfo *p_previous_expression_info) { + ShaderLanguage::Node *expr = _parse_expression(p_block, p_function_info, p_previous_expression_info); if (!expr) { //errored return nullptr; } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 1b5df7e90f3..63dca99654d 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -747,6 +747,12 @@ public: }; }; + struct ExpressionInfo { + Vector *expression = nullptr; + TokenType tt_break = TK_EMPTY; + bool is_last_expr = false; + }; + struct VarInfo { StringName name; DataType type; @@ -1143,13 +1149,13 @@ private: bool _check_restricted_func(const StringName &p_name, const StringName &p_current_function) const; bool _validate_restricted_func(const StringName &p_call_name, const CallInfo *p_func_info, bool p_is_builtin_hint = false); - Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); + Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info, const ExpressionInfo *p_previous_expression_info = nullptr); Error _parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_forbid_unknown_size, Node **r_size_expression, int *r_array_size, bool *r_unknown_size); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info); Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size); ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); - Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info); + Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info, const ExpressionInfo *p_previous_expression_info = nullptr); Error _parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); String _get_shader_type_list(const HashSet &p_shader_types) const; String _get_qualifier_str(ArgumentQualifier p_qualifier) const;