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
として定義されている。