Как Camlp5 (бывший Camlp4) анализирует выражения
Насколько я мог понять, по поиску в Интернете, похоже, что Camlp5 (бывший Camlp4) использует парсер рекурсивного спуска, в то время как ocamlyacc
основанный на LALR генератор парсера
В генераторе синтаксического анализатора LALR приоритет и ассоциативность отображаются для сдвига / уменьшения конфликтов. Мой вопрос заключается в том, как рекурсивный анализатор спуска, такой как Camlp5, может иметь дело с декларативным приоритетом оператора?
# let expr = Grammar.Entry.create gram "expr";;
# EXTEND
expr:
[ "add" LEFTA
[ x = expr; "+"; y = expr -> x + y
| x = expr; "-"; y = expr -> x - y ]
| "mult" RIGHTA
[ x = expr; "*"; y = expr -> x * y
| x = expr; "/"; y = expr -> x / y ]
| "simple" NONA
[ x = INT -> int_of_string x
| "("; e = expr; ")" -> e ] ]
;
END;;
Как это относится к леворекурсивным вызовам? Использует ли camlp5 (camlp4) подход приоритета операторов, управляемый таблицей: https://en.wikipedia.org/wiki/Operator-precedence_parser
Любые идеи или ссылки на внутреннюю работу парсера Camlp4 очень ценятся.
1 ответ
Парсер рекурсивного спуска не является табличным парсером, как LALR. Решения, принимаемые синтаксическим анализатором, жестко закодированы в теле функций (каждое правило является функцией). И действительно, CamlpN
компилирует грамматическое определение в набор взаимных рекурсивных функций. Выигрышным моментом здесь является то, что вам не нужно кодировать эти функции вручную. Таким образом, если вы изменяете грамматику, вы просто обновляете определение грамматики, и все необходимые функции обновляются для вас. В обычном рекурсивном парсере с ручным кодом вам нужно будет обновить его самостоятельно, что очень подвержено ошибкам.