Обычный способ определения грамматики SMIE языка — это определение новой глобальной переменной, которая содержит таблицу прецедентов, предоставляя набор правил BNF. Например, определение грамматики для небольшого языка, похожего на 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 "*")))))))
Несколько моментов, на которые следует обратить внимание:
begin ... end появляться где угодно.
id не имеет правой части: это не означает, что она может соответствовать только пустой строке, поскольку, как упоминалось, любая последовательность sexp может появляться где угодно.
";" как разделитель операторов separator, что SMIE может обрабатывать очень хорошо.
"," и ";" выше), лучше всего определять с помощью правил BNF, таких как (foo (foo "separator" foo) ...), которые генерируют конфликты прецедента, которые затем разрешаются путем предоставления им явного (assoc "separator").
("(" exps ")") не было необходимо для сопоставления скобок, поскольку SMIE сопоставляет любые символы, помеченные как имеющие синтаксис скобок в таблице синтаксиса. Вместо этого это правило (вместе с определением exps) делает ясным, что "," не должен появляться вне скобок.
left или right, обычно предпочтительнее помечать операторы как ассоциативные, используя assoc. По этой причине "+" и "*" определены выше как assoc, хотя язык формально определяет их как левоассоциативные.