我在搜索有关将三元运算符转换为反向波兰表示法 (RPN) 的信息时遇到了这个问题,所以虽然我没有可靠的实现来实现?:具有优先爬升的运算符,但我确实认为我可以提供一些线索使用两个堆栈将?:运算符转换为 RPN ......这类似于您给出的网页中的 Shutting Yard 算法。
(编辑)我必须指出我在这里所做的不是很有效(必须评估三元运算符的两个分支),但要演示?:在现有框架中合并新运算符 ( ) 是多么容易( RPN 转换代码)(通过声明?和:两个最低优先级)。
我想从一些示例开始,说明如何?:根据我的解析器将表达式 with 转换为 RPN ...我添加了两个运算符而不是一个,?and :,但我认为这不会有很大的不同,因为:并且?将永远放在一起(RPN和原始表达式具有相同数量的令牌更方便)。在示例中,您可以看到它是如何工作的。
示例 1:1 + ((0+1) ? 2 : 3 + 8) + 4
RPN:1 0 1 + 2 3 8 + : ? + 4 +
现在让我们评估 RPN。
1 - 将第一个元素推入堆栈,我们遇到了第一个二元运算符:
1 0 1和 operator +,我们添加顶部 2 个元素,将堆栈变成1 1
2 - 然后再推三个元素,我们遇到了第二个二元运算符:
1 1 2 3 8 +------>1 1 2 11
3 - 现在我们有:和?。这实际上告诉我们选择后续分支(堆栈顶部的第二个最顶部元素2)或替代分支(堆栈顶部11的元素) . 由于谓词为 1(真),我们选择 2 并丢弃 11。解析器弹出 3 个元素(谓词/结果/替代)并推回选择的元素(在本例中为结果分支),因此堆栈变为1
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 是等价的,因为它们可以相互转换,三元运算符应该能够以类似的方式通过 Precedence Climbing 实现。
需要做的一件事似乎是?:运算符的“优先级”(或优先级)。我在尝试 RPN 转换时实际上遇到了它。我给了问号和冒号最低优先级:
正如您从上面的示例中看到的那样,每当我们要执行?:时,优先分支和替代分支和谓词应该已经被评估,产生一个数字。这是由优先级保证的。
以下是优先级(优先级)表。
! ~> * / %> + -> &> ^> |> &&> ||> ?>:
?and的:优先级最低,在 1?2+3:4+5 这样的表达式中表示,?并且:永远不会接受它们周围的操作数。
?出现:在RPN之前。据我了解,这只是一种设计选择,因为甚至不一定必须首先拆分为 2 个运算符。:?:?
希望这可以帮助..
参考:http ://en.cppreference.com/w/cpp/language/operator_precedence