I've come across this question searching for information on transforming ternary operators to Reverse Polish Notations (RPN), so while I do not have a solid implementation for implementing the ?:
operator with Precedence Climbing, I do think I may be able to give some clue to transforming the ?:
operator to RPN using two stacks ... which is similar to the Shunting Yard algorithm in the webpage you have given.
(Edit) I have to point out what I'm doing here is not very efficient (both branches of the ternary operator must be evaluated), but to demonstrate how easy it is to incorporate a new operator (?:
) in an existing framework (the RPN transformation code) (by declaring ?
and :
with two lowest precedence levels).
I want to start with some examples of how expressions with ?:
are transformed to RPN based on my parser...
I am adding two operators instead of just one, the ?
and :
, but I don't think it makes a big difference since :
and ?
will always be put together (It's just more convenient that the RPN and the original expression have the same number of tokens). In the examples you can see how it works.
Example 1: 1 + ((0+1) ? 2 : 3 + 8) + 4
RPN: 1
0
1
+
2
3
8
+
:
?
+
4
+
Now let's evaluate the RPN.
1 - Pushing first elements into the stack and we come across the first binary operator:
1
0
1
and operator +
, we add the top 2 elements, turning the stack into 1
1
2 - Then pushing three more elements and we come across the second binary operator:
1
1
2
3
8
+
------> 1
1
2
11
3 - Now we have :
and ?
. This actually tells us to select either the consequent branch (the 2nd topmost element on top of the stack, 2
) or the alternative branch (the topmost element on the stack, 11
), based on the predicate (the 3rd topmost element on the stack, 1
). Since the predicate is 1 (true), we choose 2 and discard 11. The parser pops the 3 elements (predicate/consequent/alternative) and pushes back the chosen one (in this case, the consequent branch), so the stack becomes
1
2
4 - Consume the remaining elements:
1
2
+
------> 3
3
4
+
------> 7
Example 2: 1 + ((0+0+0?0:0) ? 2 : (3 + 8)) + 4
RPN: 1
0
0
+
0
+
0
0
:
?
2
3
8
+
:
?
+
4
+
Evaluation:
Start:
1
0
0
+
0
+
0
0
:
?
2
3
8
+
:
?
+
4
+
After adding 0 to 0:
1
0
0
+
0
0
:
?
2
3
8
+
:
?
+
4
+
After adding 0 to 0:
1
0
0
0
:
?
2
3
8
+
:
?
+
4
+
After the first :?
chooses 0
:
1
0
2
3
8
+
:
?
+
4
+
After adding 3 and 8:
1
0
2
11
:
?
+
4
+
After the ?:
chooses 11:
1
11
+
4
+
After adding 1 and 11:
12
4
+
Finally:
16
This may suggest that it's possible to transform an expression with ?:
into reverse polish notation. As the webpage says RPN and AST are equivalent in that they could be transformed into and from each other, the ternary operator should be able to be implemented with Precedence Climbing in a similar fashion.
One thing that needs be done seems to be the "priority" (or precedence) of the ?:
operator. And I have actually come across it when attempting the RPN transform. I have given question marks and colons the lowest precedence:
As you can see from the example above, whenever we are about to execute ?:
, the precedence branch and the alternative branch and the predicate should have already been evaluated, resulting in a single number. This is guaranteed by precedence.
Following is the priority (precedence) table.
!
~
> *
/
%
> +
-
> &
> ^
> |
> &&
> ||
> ?
> :
The ?
and :
are of the least priority, meaning in expressions like 1?2+3:4+5, ?
and :
will never take the operands around them.
?
precedes :
in order to make :
appear before ?
in the RPN. In my understanding this is only a design choice because :
and ?
do not even necessarily have to split into 2 operators in the first place.
Hope this helps..
Reference: http://en.cppreference.com/w/cpp/language/operator_precedence
logical-OR-expression ? expression : conditional-expression
(C) orlogical-OR-expression ? expression : assignment-expression
(C++) and conditional and assignment expressions can appear in the "middle" and in the "right" expressions. What's worse, the comma expression may appear in the "middle" as well. I wonder why the definitions are different in C and C++. I'm tagging this as C in the hope of better visibility. – Scorify