为语言定义 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 没有右侧规则:这并不意味着它仅能匹配空串,
因为前文已提到任意 S 表达式序列均可出现在任意位置。
";" 视为语句 分隔符,
SMIE 对此能很好地处理。
"," 和 ";")
最好通过 (foo (foo "separator" foo) ...) 这类 BNF 规则定义,
这类规则会产生优先级冲突,随后通过显式指定 (assoc "separator") 解决冲突。
("(" exps ")") 规则并非用于配对括号,
因为 SMIE 会自动配对语法表中标记为括号语法的任意字符。
该规则(配合 exps 的定义)实际作用是明确 "," 不应出现在括号之外。
left 或 right,
通常更适合用 assoc 将运算符标记为可结合的。
因此上述代码中 "+" 和 "*" 均定义为 assoc,
尽管该语言在形式上定义其为左结合。