Next: SMIE Lexer, Previous: Operator Precedence Grammars, Up: SMIE [Contents][Index]
ある言語にたいして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ブロックのようなsexpの任意のシーケンスがどこに、どのように出現しても自動的にそれを許容するだろう。
idは右側に何ももたない。これはidが空文字列だけにマッチ可能なことを意味しない。なぜなら上述のように任意のsexpシーケンスはどこに、どのような方法でも出現するからである。
";"をセパレーター(separator)ステートメントのかわりとして扱っている。
","や";"のような)セパレーターは、BNFルールでは(foo (foo
"separator" foo) ...)のように定義するのが最善である。これは順位の競合を生成するが、明示的に(assoc
"separator")を与えることにより解決される、
("(" exps
")")ルールにカッコをペアにする必要はなかった。(expsの定義と併せて)これはかわりに","がカッコの外に出現すべきではないことを明確にするためのルール。
leftやrightを選択することが優るという明白な理由がなければ、通常はassocを使用して演算子を結合演算子(associative)とマークするほうが優れている。この理由により上述の"+"と"*"は、たとえその言語がそれらを形式上は左結合(left
associative)と定義していてもassocとして定義されている。