diff options
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r-- | servers/visual/shader_language.cpp | 172 |
1 files changed, 137 insertions, 35 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 489b5c3771..169429af81 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1397,8 +1397,8 @@ ShaderLanguage::Operator ShaderLanguage::get_token_operator(TokenType p_type) { Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_expr) { - Vector<Node*> expressions; - Vector<TokenType> operators; + Vector<Expression> expression; + //Vector<TokenType> operators; while(true) { @@ -1605,34 +1605,33 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex parser.advance(); expr=varname; - } else if (parser.get_token_type()==TK_OP_NEG || parser.get_token_type()==TK_OP_NOT) { + } else if (parser.get_token_type()==TK_OP_SUB || parser.get_token_type()==TK_OP_NOT) { //single prefix operators TokenType token_type=parser.get_token_type(); parser.advance(); - Node *subexpr=NULL; - Error err = parse_expression(parser,p_parent,&subexpr); - if (err) - return err; + //Node *subexpr=NULL; + //Error err = parse_expression(parser,p_parent,&subexpr); + //if (err) + // return err; + + //OperatorNode *op = parser.create_node<OperatorNode>(p_parent); + + Expression e; + e.is_op=true; - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); switch(token_type) { - case TK_OP_NEG: op->op=OP_NEG; break; - case TK_OP_NOT: op->op=OP_NOT; break; + case TK_OP_SUB: e.op=TK_OP_NEG; break; + case TK_OP_NOT: e.op=TK_OP_NOT; break; //case TK_OP_PLUS_PLUS: op->op=OP_PLUS_PLUS; break; //case TK_OP_MINUS_MINUS: op->op=OP_MINUS_MINUS; break; default: ERR_FAIL_V(ERR_BUG); } - op->arguments.push_back(subexpr); - - expr=validate_operator(parser,op); + expression.push_back(e); - if (!expr) { + continue; - parser.set_error("Invalid argument for negation operator"); - return ERR_PARSE_ERROR; - } } else { print_line("found bug?"); @@ -1798,48 +1797,64 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex } */ - - expressions.push_back(expr); + Expression e; + e.is_op=false; + e.node=expr; + expression.push_back(e); if (is_token_operator(parser.get_token_type())) { - operators.push_back(parser.get_token_type()); + Expression o; + o.is_op=true; + o.op=parser.get_token_type(); + expression.push_back(o); parser.advance(); } else { break; } } - ERR_FAIL_COND_V(expressions.size()!=(operators.size()+1),ERR_BUG); + /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ - while(expressions.size()>1) { + while(expression.size()>1) { int next_op=-1; int min_priority=0xFFFFF; + bool is_unary=false; + + for(int i=0;i<expression.size();i++) { - for(int i=0;i<operators.size();i++) { + if (!expression[i].is_op) { + + continue; + } + + bool unary=false; int priority; - switch(operators[i]) { + switch(expression[i].op) { + + case TK_OP_NOT: priority=0; unary=true; break; + case TK_OP_NEG: priority=0; unary=true; break; - case TK_OP_MUL: priority=0; break; - case TK_OP_DIV: priority=0; break; + case TK_OP_MUL: priority=1; break; + case TK_OP_DIV: priority=1; break; - case TK_OP_ADD: priority=1; break; - case TK_OP_SUB: priority=1; break; + case TK_OP_ADD: priority=2; break; + case TK_OP_SUB: priority=2; break; // shift left/right =2 - case TK_OP_LESS: priority=3; break; - case TK_OP_LESS_EQUAL: priority=3; break; - case TK_OP_GREATER: priority=3; break; - case TK_OP_GREATER_EQUAL: priority=3; break; + case TK_OP_LESS: priority=4; break; + case TK_OP_LESS_EQUAL: priority=4; break; + case TK_OP_GREATER: priority=4; break; + case TK_OP_GREATER_EQUAL: priority=4; break; - case TK_OP_EQUAL: priority=4; break; - case TK_OP_NOT_EQUAL: priority=4; break; + case TK_OP_EQUAL: priority=5; break; + case TK_OP_NOT_EQUAL: priority=5; break; //bit and =5 //bit xor =6 @@ -1865,6 +1880,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex // <= is used for right to left next_op=i; min_priority=priority; + is_unary=unary; } } @@ -1872,7 +1888,92 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex ERR_FAIL_COND_V(next_op==-1,ERR_BUG); // OK! create operator.. + // OK! create operator.. + if (is_unary) { + + int expr_pos=next_op; + while(expression[expr_pos].is_op) { + + expr_pos++; + if (expr_pos==expression.size()) { + //can happen.. + parser.set_error("Unexpected end of expression.."); + return ERR_BUG; + } + } + + //consecutively do unary opeators + for(int i=expr_pos-1;i>=next_op;i--) { + + OperatorNode *op = parser.create_node<OperatorNode>(p_parent); + op->op=get_token_operator(expression[i].op); + op->arguments.push_back(expression[i+1].node); + + expression[i].is_op=false; + expression[i].node=validate_operator(parser,op); + if (!expression[i].node) { + + String at; + for(int i=0;i<op->arguments.size();i++) { + if (i>0) + at+=" and "; + at+=get_datatype_name(compute_node_type(op->arguments[i])); + + } + parser.set_error("Invalid argument to unary operator "+String(token_names[op->op])+": "+at); + return ERR_PARSE_ERROR; + } + expression.remove(i+1); + } + } else { + + if (next_op <1 || next_op>=(expression.size()-1)) { + parser.set_error("Parser bug.."); + ERR_FAIL_V(ERR_BUG); + } + + OperatorNode *op = parser.create_node<OperatorNode>(p_parent); + op->op=get_token_operator(expression[next_op].op); + + if (expression[next_op-1].is_op) { + + parser.set_error("Parser bug.."); + ERR_FAIL_V(ERR_BUG); + } + + if (expression[next_op+1].is_op) { + // this is not invalid and can really appear + // but it becomes invalid anyway because no binary op + // can be followed by an unary op in a valid combination, + // due to how precedence works, unaries will always dissapear first + + parser.set_error("Parser bug.."); + + } + + + op->arguments.push_back(expression[next_op-1].node); //expression goes as left + op->arguments.push_back(expression[next_op+1].node); //next expression goes as right + + //replace all 3 nodes by this operator and make it an expression + expression[next_op-1].node=validate_operator(parser,op); + if (!expression[next_op-1].node) { + + String at; + for(int i=0;i<op->arguments.size();i++) { + if (i>0) + at+=" and "; + at+=get_datatype_name(compute_node_type(op->arguments[i])); + + } + parser.set_error("Invalid arguments to operator "+String(token_names[op->op])+": "+at); + return ERR_PARSE_ERROR; + } + expression.remove(next_op); + expression.remove(next_op); + } +#if 0 OperatorNode *op = parser.create_node<OperatorNode>(p_parent); op->op=get_token_operator(operators[next_op]); @@ -1896,10 +1997,11 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex expressions.remove(next_op+1); operators.remove(next_op); +#endif } - *r_expr=expressions[0]; + *r_expr=expression[0].node; return OK; |