Browse Source

Merge pull request #94352 from Chaosus/shader_ternary_fix

Fix multiple ternary expressions to be used without parenthesis
Rémi Verschelde 11 months ago
parent
commit
10a92287c6
2 changed files with 44 additions and 5 deletions
  1. 36 3
      servers/rendering/shader_language.cpp
  2. 8 2
      servers/rendering/shader_language.h

+ 36 - 3
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> expression;
 
 	//Vector<TokenType> 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;
 	}

+ 8 - 2
servers/rendering/shader_language.h

@@ -747,6 +747,12 @@ public:
 		};
 	};
 
+	struct ExpressionInfo {
+		Vector<Expression> *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<String> &p_shader_types) const;
 	String _get_qualifier_str(ArgumentQualifier p_qualifier) const;