Browse Source

Fix shader array parsing in variable declaration

Yuri Roubinsky 3 years ago
parent
commit
25a2241e7d
2 changed files with 66 additions and 56 deletions
  1. 65 55
      servers/rendering/shader_language.cpp
  2. 1 1
      servers/rendering/shader_language.h

+ 65 - 55
servers/rendering/shader_language.cpp

@@ -4399,13 +4399,14 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const Function
 	return OK;
 	return OK;
 }
 }
 
 
-Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size) {
+Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, Node *&r_size_expression, int &r_array_size, bool &r_is_unknown_size) {
 	TkPos pos = _get_tkpos();
 	TkPos pos = _get_tkpos();
 	Token tk = _get_token();
 	Token tk = _get_token();
 
 
 	if (tk.type == TK_BRACKET_CLOSE) {
 	if (tk.type == TK_BRACKET_CLOSE) {
 		r_is_unknown_size = true;
 		r_is_unknown_size = true;
 	} else {
 	} else {
+		int size = 0;
 		if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
 		if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
 			_set_tkpos(pos);
 			_set_tkpos(pos);
 			int array_size = 0;
 			int array_size = 0;
@@ -4413,13 +4414,13 @@ Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const Function
 			if (!n) {
 			if (!n) {
 				return ERR_PARSE_ERROR;
 				return ERR_PARSE_ERROR;
 			}
 			}
-			p_decl->size = array_size;
-			p_node->size_expression = n;
+			size = array_size;
+			r_size_expression = n;
 		} else if (((int)tk.constant) > 0) {
 		} else if (((int)tk.constant) > 0) {
-			p_decl->size = (uint32_t)tk.constant;
+			size = (uint32_t)tk.constant;
 		}
 		}
 
 
-		if (p_decl->size <= 0) {
+		if (size <= 0) {
 			_set_error("Expected single integer constant > 0");
 			_set_error("Expected single integer constant > 0");
 			return ERR_PARSE_ERROR;
 			return ERR_PARSE_ERROR;
 		}
 		}
@@ -4430,7 +4431,7 @@ Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const Function
 			return ERR_PARSE_ERROR;
 			return ERR_PARSE_ERROR;
 		}
 		}
 
 
-		r_array_size = p_decl->size;
+		r_array_size = size;
 	}
 	}
 
 
 	return OK;
 	return OK;
@@ -6464,49 +6465,44 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
 				return ERR_PARSE_ERROR;
 				return ERR_PARSE_ERROR;
 			}
 			}
 
 
-			tk = _get_token();
-
 			Node *vardecl = nullptr;
 			Node *vardecl = nullptr;
+			int array_size = 0;
+			bool fixed_array_size = false;
+			bool first = true;
 
 
-			while (true) {
+			do {
 				bool unknown_size = false;
 				bool unknown_size = false;
-				int array_size = 0;
+				Node *size_expr = nullptr;
 
 
 				ArrayDeclarationNode *anode = nullptr;
 				ArrayDeclarationNode *anode = nullptr;
 				ArrayDeclarationNode::Declaration adecl;
 				ArrayDeclarationNode::Declaration adecl;
 
 
-				if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
-					_set_error("Expected identifier or '[' after datatype.");
-					return ERR_PARSE_ERROR;
-				}
+				tk = _get_token();
 
 
-				if (tk.type == TK_BRACKET_OPEN) {
-					anode = alloc_node<ArrayDeclarationNode>();
+				if (first) {
+					first = false;
 
 
-					if (is_struct) {
-						anode->struct_name = struct_name;
-						anode->datatype = TYPE_STRUCT;
-					} else {
-						anode->datatype = type;
+					if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+						_set_error("Expected identifier or '[' after datatype.");
+						return ERR_PARSE_ERROR;
 					}
 					}
 
 
-					anode->precision = precision;
-					anode->is_const = is_const;
-					vardecl = (Node *)anode;
-
-					adecl.size = 0U;
-					adecl.single_expression = false;
+					if (tk.type == TK_BRACKET_OPEN) {
+						Error error = _parse_local_array_size(p_block, p_function_info, size_expr, array_size, unknown_size);
+						if (error != OK) {
+							return error;
+						}
+						adecl.single_expression = false;
+						adecl.size = array_size;
 
 
-					Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, array_size, unknown_size);
-					if (error != OK) {
-						return error;
+						fixed_array_size = true;
+						tk = _get_token();
 					}
 					}
-					tk = _get_token();
+				}
 
 
-					if (tk.type != TK_IDENTIFIER) {
-						_set_error("Expected identifier!");
-						return ERR_PARSE_ERROR;
-					}
+				if (tk.type != TK_IDENTIFIER) {
+					_set_error("Expected identifier!");
+					return ERR_PARSE_ERROR;
 				}
 				}
 
 
 				StringName name = tk.text;
 				StringName name = tk.text;
@@ -6544,8 +6540,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
 
 
 				tk = _get_token();
 				tk = _get_token();
 
 
+				bool is_array_decl = var.array_size > 0 || unknown_size;
+
 				if (tk.type == TK_BRACKET_OPEN) {
 				if (tk.type == TK_BRACKET_OPEN) {
-					if (var.array_size > 0 || unknown_size) {
+					if (is_array_decl) {
 						_set_error("Array size is already defined!");
 						_set_error("Array size is already defined!");
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
@@ -6555,28 +6553,37 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
 
 
-					anode = alloc_node<ArrayDeclarationNode>();
-					if (is_struct) {
-						anode->struct_name = struct_name;
-						anode->datatype = TYPE_STRUCT;
-					} else {
-						anode->datatype = type;
+					Error error = _parse_local_array_size(p_block, p_function_info, size_expr, var.array_size, unknown_size);
+					if (error != OK) {
+						return error;
 					}
 					}
-					anode->precision = precision;
-					anode->is_const = is_const;
-					vardecl = (Node *)anode;
 
 
-					adecl.size = 0U;
 					adecl.single_expression = false;
 					adecl.single_expression = false;
+					adecl.size = var.array_size;
+					array_size = var.array_size;
 
 
-					Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, var.array_size, unknown_size);
-					if (error != OK) {
-						return error;
-					}
+					is_array_decl = true;
 					tk = _get_token();
 					tk = _get_token();
 				}
 				}
 
 
-				if (var.array_size > 0 || unknown_size) {
+				if (is_array_decl) {
+					{
+						anode = alloc_node<ArrayDeclarationNode>();
+
+						if (is_struct) {
+							anode->struct_name = struct_name;
+							anode->datatype = TYPE_STRUCT;
+						} else {
+							anode->datatype = type;
+						}
+
+						anode->precision = precision;
+						anode->is_const = is_const;
+						anode->size_expression = size_expr;
+
+						vardecl = (Node *)anode;
+					}
+
 					bool full_def = false;
 					bool full_def = false;
 
 
 					if (tk.type == TK_OP_ASSIGN) {
 					if (tk.type == TK_OP_ASSIGN) {
@@ -6794,6 +6801,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
 						}
 						}
 					}
 					}
 
 
+					array_size = var.array_size;
 					anode->declarations.push_back(adecl);
 					anode->declarations.push_back(adecl);
 				} else if (tk.type == TK_OP_ASSIGN) {
 				} else if (tk.type == TK_OP_ASSIGN) {
 					VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
 					VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
@@ -6862,22 +6870,24 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
 				}
 				}
 
 
 				p_block->statements.push_back(vardecl);
 				p_block->statements.push_back(vardecl);
-
 				p_block->variables[name] = var;
 				p_block->variables[name] = var;
+
+				if (!fixed_array_size) {
+					array_size = 0;
+				}
+
 				if (tk.type == TK_COMMA) {
 				if (tk.type == TK_COMMA) {
 					if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
 					if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
 						_set_error("Multiple declarations in 'for' loop are not implemented yet.");
 						_set_error("Multiple declarations in 'for' loop are not implemented yet.");
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
-					tk = _get_token();
-					//another variable
 				} else if (tk.type == TK_SEMICOLON) {
 				} else if (tk.type == TK_SEMICOLON) {
 					break;
 					break;
 				} else {
 				} else {
 					_set_error("Expected ',' or ';' after variable");
 					_set_error("Expected ',' or ';' after variable");
 					return ERR_PARSE_ERROR;
 					return ERR_PARSE_ERROR;
 				}
 				}
-			}
+			} while (tk.type == TK_COMMA); //another variable
 		} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
 		} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
 			//a sub block, just because..
 			//a sub block, just because..
 			BlockNode *block = alloc_node<BlockNode>();
 			BlockNode *block = alloc_node<BlockNode>();

+ 1 - 1
servers/rendering/shader_language.h

@@ -1001,7 +1001,7 @@ private:
 
 
 	Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
 	Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
 	Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info);
 	Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info);
-	Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size);
+	Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, Node *&r_size_expression, int &r_array_size, bool &r_is_unknown_size);
 
 
 	Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
 	Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
 	Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
 	Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);