Гарольд пишет:
Я помню, как читал давным-давно алгоритм, который преобразовал
алгебраические выражения в RPN для легкой оценки. Каждое значение инфикса или
оператор или скобки были представлены вагоном на
трек. Один
тип машины откололся на другую трассу, а другой продолжал движение прямо
вперед. Я не помню детали (очевидно!), Но всегда думал, что это
было бы интересно, чтобы код. Это вернулся, когда я писал 6800 (не
68000) код сборки.
Это «алгоритм маневрового двора»
и это то, что большинство машинных парсеров
использовать. Смотрите статью о разборе в
Wikipedia. Простой способ кодировать
Алгоритм маневрового двора должен использовать два
стеки. Одним из них является стек "толчок" и
другой «уменьшить» или «результат»
стек. Пример:
pstack = () // пусто rstack = ()
вход: 1 + 2 * 3 приоритет = 10 // низший
уменьшить = 0 // не уменьшать
начало: токен '1': номер, положить в
pstack (push) токен '+': isoperator
установить приоритет = 2, если приоритет <
previous_operator_precedence затем
Reduce () // см. ниже положить «+» в
токен pstack (push) '2': isnumber,
положить в pstack (push) токен '*':
isoperator, установить приоритет = 1, положить в
pstack (push) // проверяем приоритет как
// над токеном '3': isnumber, вставляем
pstack (push) конец ввода, нужно
уменьшить (цель пустого pstack) уменьшить ()
// сделано
чтобы уменьшить попсовые элементы от толчка
сложить и положить их в результат
стек, всегда поменяйте местами 2 лучших
Pstack, если они имеют форму
'оператор' 'номер':
pstack: '1' '+' '2' '' '3' rstack: ()
... pstack: () rstack: '3' '2' '' '1'
'+'
если бы выражение было:
1 * 2 + 3
тогда триггер уменьшения будет иметь
было чтение токена '+'
который имеет более низкий приоритет, чем
«*» уже нажал, так что было бы
сделано:
pstack: '1' '' '2' rstack: () ...
pstack: () rstack: '1' '2' ''
, затем нажмите «+», затем «3» и
затем, наконец, уменьшилось:
pstack: '+' '3' rstack: '1' '2' ''
... pstack: () rstack: '1' '2' '' '3'
'+'
Итак, короткая версия: push-номера,
при нажатии операторы проверяют
приоритет предыдущего оператора.
Если бы он был выше, чем у оператора
это должно быть выдвинуто сейчас, сначала
уменьшить, затем протолкнуть ток
оператор. Чтобы справиться с парнями, просто сохраните
приоритет «предыдущего»
оператор и поставить отметку на pstack
что говорит алгоритм уменьшения
прекратить уменьшать при решении изнутри
парной пары. Закрытие парен
вызывает сокращение, как и конец
ввода, а также удаляет открытые
родословная от pstack, и
восстанавливает «предыдущую операцию»
приоритет, чтобы анализ мог продолжаться
после близкого парня, где он оставил
выкл. Это можно сделать с помощью рекурсии
или без (подсказка: используйте стек для хранения
предыдущий приоритет, когда
столкнувшись с '(' ...).
обобщенная версия это использовать
реализован генератор парсера
Алгоритм маневрового двора, например с помощью
YACC или бизон или Taccle (аналог Tcl
Yacc).
Peter