I have implemented shunting-yard algorithm to parse arithmetic string-expressions from infix to postfix-notation.
I now also want to parse expressions with relational operators and Ternary conditional. Considering C++ Operator Precedence i added those operators with the lowest precedence and right-associativity
for ?
and :
and the second-lowest and left-associativity
for >
and <
.
When i now parse an expression like: A>B?C:D
(where A, B, C and D can be any valid arithmetic expression) i would expect: A B > C D : ?
, but i get A B C D : ? <
. When i use Parentheses to evaluate the Condition first (A>B)?C:D
it works. A mixed expression like (1+2<3+4)?C:D
gives me 1 2 + 3 4 + < C D : ?
which seems also legit to me. (A<B)?5+6:C
gives me A B < 5 6 : + ?
which again is messed up. Again, (A<B)?(5+6):C
would fix that.
As stated in the comments, evaluating conditions first and the proceed with the left arithmetic expression would also be fine. But i really did not stumble upon an algorithm for evaluating expressions with relational and ternary operators in my research yet. Any help, even if pointing out an algorithm would be very appreciated
Here is the implementation of shunting-yard:
QQueue<QString> ShuntingYard::infixToPostfixWithConditionals(const QString& expression)
{
QStack<QString> stack;
QQueue<QString> queue;
QString token;
QStringList tokens = splitExpression(expression);
Q_FOREACH(QString token, tokens)
{
if (isDefineOrNumber(token))
queue.enqueue(token);
if (isFunction(token))
stack.push(token);
if (isOperator(token))
{
while (!stack.isEmpty() && isOperator(stack.top()) && isLeftAssociativeOperator(token) && !hasHigherPrecedence(token, stack.top()))
queue.enqueue(stack.pop());
stack.push(token);
}
if (isLeftParenthese(token))
stack.push(token);
else if (isRightParenthese(token))
{
while (!isLeftParenthese(stack.top()))
{
if (stack.isEmpty())
break;
if (isOperator(stack.top()))
queue.enqueue(stack.pop());
}
stack.pop();
if (isFunction(stack.top()))
queue.enqueue(stack.pop());
}
}
while (!stack.isEmpty())
{
if (isLeftParenthese(stack.top()))
break;
queue.enqueue(stack.pop());
}
return queue;
}
EDIT: made code and description more concise for readabilility
Another EDIT: Treating ?: as left-associative gave me the expected output
Now, regarding this question about the associativity of ternary conditionals. If i input a<b?a:b?c:d
i get a b < a b c d : ? : ?
, where a < b
will be evaluated first, which is correct, due to its higher precedence, but then b ? c : d
will be evaluated first, which is the correct right-to-left order. Confusing.