Как расширить алгоритм маневровой станции, изначально предназначенный для бинарных операторов, для поддержки условного тернарного оператора ("a ? b: c")? Я не видел ответа на этот вопрос здесь, и он у меня есть, поэтому я публикую его.
Расширение алгоритма маневровой станции для поддержки условного тернарного оператора
Ответы (2)
Я сделал это, добавив три новых оператора:
- "?" троичный-открытый-если
- ":" троичное-иначе
- тернарно-закрыто-если
Только первые два будут созданы непосредственно при чтении исходного выражения.
Однако в выходных данных будет существовать только третий (RPN исходного выражения).
Тернарный-open-if помещается в операторы складываются всякий раз, когда "?" виден.
Троичное-else никогда не помещается в стек. Скорее, стек выталкивается до тех пор, пока не будет найдено троичное открытое условие, после чего троичное открытое условие заменяется троичным закрытым условием (таким образом указывая, что мы находимся в другой части условного оператора).< br> Все три оператора имеют более высокий приоритет, чем все остальные операторы (более высокий приоритет означает, что они оцениваются ПОСЛЕ других операторов).
Тернарные операторы if имеют такой же приоритет и правильную ассоциативность (как в C), что означает, что троичный- if никогда не вызовет появление другого троичного-if.
Троичное-else имеет более высокий приоритет, чем троичное-ifs, и его ассоциативность не имеет значения (поскольку оно никогда не помещается в стек). Таким образом, при встрече с троичным открытым-если он преобразует его в закрытый, как упоминалось ранее.
При встрече с троичным закрытым-если он извлекает его.
Примеры (тройное-закрытое-если обозначено как "?:"):
- "a ? b : c" -->
"a b c ?:" - "a ? b : x ? y : z" -->
"a b x y z ?: ?:" - "a ? x ? y : z : b" -->
"a x y z ?: b ?:"
Этот метод сложнее объяснить, чем реализовать, и он вносит небольшое изменение в алгоритм, поэтому, если у кого-то есть более простое решение, опубликуйте его.
Для тех, кто все еще ищет здесь, условный тернарный оператор также может быть реализован как функция ЕСЛИ с тремя аргументами:
IF([boolean], [expr_if_true], [expr_if_false])
Например, чтобы преобразовать IF(5 > 4, 9, 8)
в обратную польскую нотацию путем расширения алгоритма маневровой станции, выполните следующие действия:
+-------+---------------------------------------------------+--------------+----------------+
| Token | Action | RPN Output | Operator stack |
+-------+---------------------------------------------------+--------------+----------------+
| IF | Push token to stack | | IF |
| ( | Push token to stack | | IF ( |
| 5 | Add token to output | 5 | IF ( |
| > | Push token to stack | 5 | 15 ( > |
| 4 | Add token to output | 5 4 | IF ( > |
| , | Pop from stack onto output until left parenthesis | 5 4 > | IF ( |
| 9 | Add token to output | 5 4 > 9 | IF ( |
| , | Pop from stack onto output until left parenthesis | 5 4 > 9 | IF ( |
| 8 | Add token to output | 5 4 > 9 8 | IF ( |
| ) | Pop from stack onto output until left parenthesis | 5 4 > 9 8 | IF |
| end | Pop entire stack onto output | 5 4 > 9 8 IF | |
+-------+---------------------------------------------------+--------------+----------------+
Постфикс оценивается как:
+-------+------------------------------------------------------------------------------------------+-------+
| Token | Action | Stack |
+-------+------------------------------------------------------------------------------------------+-------+
| 5 | Push to stack | 5 |
| 4 | Push to stack | 4 |
| > | Pop from stack twice (5, 4), evaluate (5 > 4) and push onto stack | TRUE |
| 9 | Push onto stack | 9 |
| 8 | Push onto stack | 8 |
| IF | Pop from stack thrice (TRUE, 9, 8), evaluate (IF TRUE THEN 9 ELSE 8) and push onto stack | 9 |
+-------+------------------------------------------------------------------------------------------+-------+