|
@@ -936,6 +936,8 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|
|
case GDTokenizer::TK_OP_BIT_OR: op=OperatorNode::OP_BIT_OR ; break;
|
|
|
case GDTokenizer::TK_OP_BIT_XOR: op=OperatorNode::OP_BIT_XOR ; break;
|
|
|
case GDTokenizer::TK_PR_EXTENDS: op=OperatorNode::OP_EXTENDS; break;
|
|
|
+ case GDTokenizer::TK_CF_IF: op=OperatorNode::OP_TERNARY_IF; break;
|
|
|
+ case GDTokenizer::TK_CF_ELSE: op=OperatorNode::OP_TERNARY_ELSE; break;
|
|
|
default: valid=false; break;
|
|
|
}
|
|
|
|
|
@@ -958,6 +960,7 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|
|
int next_op=-1;
|
|
|
int min_priority=0xFFFFF;
|
|
|
bool is_unary=false;
|
|
|
+ bool is_ternary=false;
|
|
|
|
|
|
for(int i=0;i<expression.size();i++) {
|
|
|
|
|
@@ -971,6 +974,8 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|
|
int priority;
|
|
|
|
|
|
bool unary=false;
|
|
|
+ bool ternary=false;
|
|
|
+ bool error=false;
|
|
|
|
|
|
switch(expression[i].op) {
|
|
|
|
|
@@ -1001,25 +1006,27 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|
|
case OperatorNode::OP_EQUAL: priority=8; break;
|
|
|
case OperatorNode::OP_NOT_EQUAL: priority=8; break;
|
|
|
|
|
|
+
|
|
|
case OperatorNode::OP_IN: priority=10; break;
|
|
|
-
|
|
|
+
|
|
|
case OperatorNode::OP_NOT: priority=11; unary=true; break;
|
|
|
case OperatorNode::OP_AND: priority=12; break;
|
|
|
case OperatorNode::OP_OR: priority=13; break;
|
|
|
-
|
|
|
- // ?: = 10
|
|
|
-
|
|
|
- case OperatorNode::OP_ASSIGN: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_ADD: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_SUB: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_MUL: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_DIV: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_MOD: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_BIT_AND: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_BIT_OR: priority=14; break;
|
|
|
- case OperatorNode::OP_ASSIGN_BIT_XOR: priority=14; break;
|
|
|
+
|
|
|
+ case OperatorNode::OP_TERNARY_IF: priority=14; ternary=true; break;
|
|
|
+ case OperatorNode::OP_TERNARY_ELSE: priority=14; error=true; break; // Errors out when found without IF (since IF would consume it)
|
|
|
+
|
|
|
+ case OperatorNode::OP_ASSIGN: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_ADD: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_SUB: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_MUL: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_DIV: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_MOD: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_BIT_AND: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_BIT_OR: priority=15; break;
|
|
|
+ case OperatorNode::OP_ASSIGN_BIT_XOR: priority=15; break;
|
|
|
|
|
|
|
|
|
default: {
|
|
@@ -1030,11 +1037,16 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|
|
}
|
|
|
|
|
|
if (priority<min_priority) {
|
|
|
+ if(error) {
|
|
|
+ _set_error("Unexpected operator");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
// < is used for left to right (default)
|
|
|
// <= is used for right to left
|
|
|
next_op=i;
|
|
|
min_priority=priority;
|
|
|
is_unary=unary;
|
|
|
+ is_ternary=ternary;
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -1075,6 +1087,62 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
|
|
|
}
|
|
|
|
|
|
|
|
|
+ } else if(is_ternary) {
|
|
|
+ if (next_op <1 || next_op>=(expression.size()-1)) {
|
|
|
+ _set_error("Parser bug..");
|
|
|
+ ERR_FAIL_V(NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(next_op>=(expression.size()-2) || expression[next_op+2].op != OperatorNode::OP_TERNARY_ELSE) {
|
|
|
+ _set_error("Expected else after ternary if.");
|
|
|
+ ERR_FAIL_V(NULL);
|
|
|
+ }
|
|
|
+ if(next_op>=(expression.size()-3)) {
|
|
|
+ _set_error("Expected value after ternary else.");
|
|
|
+ ERR_FAIL_V(NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ OperatorNode *op = alloc_node<OperatorNode>();
|
|
|
+ op->op=expression[next_op].op;
|
|
|
+ op->line=op_line; //line might have been changed from a \n
|
|
|
+
|
|
|
+ if (expression[next_op-1].is_op) {
|
|
|
+
|
|
|
+ _set_error("Parser bug..");
|
|
|
+ ERR_FAIL_V(NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
+
|
|
|
+ _set_error("Unexpected two consecutive operators after ternary if.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (expression[next_op+3].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
|
|
|
+
|
|
|
+ _set_error("Unexpected two consecutive operators after ternary else.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ op->arguments.push_back(expression[next_op+1].node); //next expression goes as first
|
|
|
+ op->arguments.push_back(expression[next_op-1].node); //left expression goes as when-true
|
|
|
+ op->arguments.push_back(expression[next_op+3].node); //expression after next goes as when-false
|
|
|
+
|
|
|
+ //replace all 3 nodes by this operator and make it an expression
|
|
|
+ expression[next_op-1].node=op;
|
|
|
+ expression.remove(next_op);
|
|
|
+ expression.remove(next_op);
|
|
|
+ expression.remove(next_op);
|
|
|
+ expression.remove(next_op);
|
|
|
} else {
|
|
|
|
|
|
if (next_op <1 || next_op>=(expression.size()-1)) {
|