我在搜索关于将三元操作符转换为逆波兰表达式(RPN)的信息时遇到了这个问题,因此虽然我没有一个实现使用Precedence Climbing来实现
?:
运算符的坚实方法,但我认为我可以通过使用两个堆栈来给出一些将
?:
运算符转换为RPN的线索……这与您提供的网页中的Shunting Yard算法类似。
(编辑)我必须指出我在这里做的事情不是很高效(三元运算符的两个分支都必须被评估),但是为了演示如何在现有框架(RPN转换代码)中合并新运算符(
?:
)(通过声明具有两个最低优先级的
?
和
:
),我认为这很容易。
我想从一些示例开始,展示如何基于我的解析器将带有
?:
的表达式转换为RPN……我添加了
两个运算符而不是只有一个,即
?
和
:
,但我认为这并没有太大的区别,因为
:
和
?
总是会放在一起(RPN和原始表达式具有相同数量的标记只是更方便)。在下面的示例中,您可以看到它是如何工作的。
示例1:
1 + ((0+1) ? 2 : 3 + 8) + 4
RPN:
1
0
1
+
2
3
8
+
:
?
+
4
+
现在让我们来评估RPN。
1-将第一个元素推入堆栈,并遇到第一个二进制运算符:
1
0
1
和运算符
+
,我们添加顶部2个元素,将堆栈变成
1
1
2-然后再推入三个元素,并遇到第二个二进制运算符:
1
1
2
3
8
+
------>
1
1
2
11
3 - 现在我们有:
和?
。这实际上告诉我们根据谓词(栈中第三个元素1
)选择结论分支(栈中第二个顶部元素2
)或可选分支(栈中顶部元素11
)。由于谓词为1(真),我们选择2并丢弃11。解析器弹出3个元素(谓词/结论分支/可选分支)并推回所选的元素(在本例中是结论分支),因此堆栈变为
1
2
4- 消耗剩余的元素:
1
2
+
------> 3
3
4
+
------> 7
示例2: 1 + ((0+0+0?0:0) ? 2 : (3 + 8)) + 4
RPN:1
0
0
+
0
+
0
0
:
?
2
3
8
+
:
?
+
4
+
评估:
开始:
1
0
0
+
0
+
0
0
:
?
2
3
8
+
:
?
+
4
+
添加0到0后:
1
0
0
+
0
0
:
?
2
3
8
+
:
?
+
4
+
在将0加入0之后:
1
0
0
0
:
?
2
3
8
+
:
?
+
4
+
在第一个:?
选择了0
之后:
1
0
2
3
8
+
:
?
+
4
+
在添加3和8之后:
1
0
2
11
:
?
+
4
+
在?:
选择了11之后:
1
11
+
4
+
在添加1和11之后:
12
4
+
最终结果为:
16
这可能表明可以将带有?:
的表达式转换为逆波兰表示法。正如网页所说,RPN和AST是等效的,因为它们可以相互转换,三元运算符应该也可以用类似的方式使用优先级爬升实现。
需要做的一件事似乎是?:
运算符的“优先级”(或优先级)。当我尝试进行RPN转换时,我确实遇到了这个问题。我已经赋予问号和冒号最低的优先级:
从上面的例子中可以看出,每当我们要执行?:
时,precedence branch、alternative branch和predicate都应该已经被计算出一个数字。这是由优先级保证的。
以下是优先级表格。
!
~
> *
/
%
> +
-
> &
> ^
> |
> &&
> ||
> ?
> :
在表达式中,?
和 :
的优先级最低,它们不会取周围的操作数。
?
在逆波兰表达式中排在 :
前面,这只是一种设计选择,因为如果 :
和 ?
不必分成两个运算符,则可以不这样做。
希望这有所帮助..
引用文献:http://en.cppreference.com/w/cpp/language/operator_precedence