Next: トークンの定義, Previous: 演算子順位文法, 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
として定義されている。