Определение грамматики языка
Обычный способ определения грамматики SMIE для языка — определение новой глобальной переменной, содержащей таблицу приоритетов, с помощью набора правил БНФ. Например, определение грамматики для небольшого языка, похожего на Pascal, может выглядеть так:
(require 'smie) (defvar sample-smie-grammar (smie-prec2->grammar (smie-bnf->prec2
'((id)
(inst ("begin" insts "end")
("if" exp "then" inst "else" inst)
(id ":=" exp)
(exp))
(insts (insts ";" insts) (inst))
(exp (exp "+" exp)
(exp "*" exp)
("(" exps ")"))
(exps (exps "," exps) (exp)))
'((assoc ";"))
'((assoc ","))
'((assoc "+") (assoc "*")))))
Несколько замечаний:
- Вышеприведенная грамматика не упоминает синтаксис вызовов функций явно: SMIE автоматически позволит любому последовательности sexp, например, идентификаторам, скобкам или
begin ... endблокам, появляться в любом месте. - Категория грамматики
idне имеет правой части: это не означает, что она может соответствовать только пустой строке, поскольку, как уже упоминалось, любая последовательность sexp может появляться в любом месте. - Поскольку нетерминалы не могут появляться последовательно в грамматике БНФ, трудно правильно обработать токены, которые действуют как разделители, поэтому вышеприведенная грамматика рассматривает
";"как разделитель операторов, что SMIE обрабатывает очень хорошо. - Разделители, используемые в последовательностях (например,
","и";"выше), лучше всего определяются с помощью правил БНФ, таких как(foo (foo "separator" foo) ...), которые генерируют конфликты приоритетов, которые затем разрешаются, присваивая им явный(assoc "separator"). - Правило
("(" exps ")")не было нужно для пар скобок, поскольку SMIE будет парсить любые символы, помеченные как имеющие синтаксис скобок в таблице синтаксиса. Вместо этого это правило (вместе с определениемexps) делает ясным, что","не должно появляться вне скобок. - Вместо одной таблицы precs для разрешения конфликтов предпочтительнее иметь несколько таблиц, чтобы часть БНФ грамматики могла указывать относительные приоритеты, где это возможно.
- Если нет веских причин предпочесть
leftилиright, то обычно предпочтительнее маркировать операторы как ассоциативные, используяassoc. По этой причине"+"и"*"определены выше какassoc, хотя язык формально определяет их как левоассоциативные.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/SMIE-Grammar.html