生成されたパーサーでMenhirのインクリメンタル解析 APIとイントロスペクション APIを使用しようとしています。たとえば、特定の LR(1) スタック エントリに関連付けられたセマンティック値を決定したいとします。つまり、パーサーによって以前に消費されたトークンです。
Menhir の type にカプセル化された抽象解析チェックポイントが与えられると'a env
、LR オートマトンから「スタック要素」を抽出できます。次のようになります。
type element = | Element: 'a lr1state * 'a * position * position -> element
type 要素は、LR(1) オートマトンのスタック内の 1 つのエントリを記述します。フォームのスタック要素では
Element (s, v, startp, endp)
、s
は (非初期) 状態でv
あり、セマンティック値です。値v
は、状態の入力シンボル A に関連付けられs
ます。つまり、値v
は状態に入る直前にスタックにプッシュされましたs
。したがって、一部の type'a
の場合、状態s
には type が'a lr1state
あり、値v
には type'a
...があります。値を使って何か有用なことを行うには、状態を調べ
v
て型に関する情報を取得する必要があります。これまでのところ、型は抽象的であるため、検査する方法はありません。検査 API (§9.3) は、この目的のためにさらにツールを提供します。'a
s
'a lr1state
s
よし、かっこいい!そこで、インスペクション API に飛び込みます。
端末の型は、一般化された代数データ型 (GADT) です。タイプ 'a terminal の値は、終端記号を表します (セマンティック値なし)。インデックス 'a は、このシンボルに関連付けられた意味値の型です ...
type _ terminal = | T_A : unit terminal | T_B : int terminal
タイプ 'a 非終端記号も GADT です。タイプ 'a 非終端記号の値は、非終端記号 (意味値なし) を表します。インデックス 'a は、このシンボルに関連付けられた意味値の型です ...
type _ nonterminal = | N_main : thing nonterminal
これらをつなぎ合わせると、次のようなものが得られます (ここで、「コマンド」は私の文法の非終端記号の 1 つであり、したがってN_command
ですstring nonterminal
)。
let current_command (env : 'a env) =
let rec f i =
match Interpreter.get i env with
| None -> None
| Some Interpreter.Element (lr1state, v, _startp, _endp) ->
match Interpreter.incoming_symbol lr1state with
| Interpreter.N Interpreter.N_command -> Some v
| _ -> f (i + 1)
in
f 0
残念ながら、これは私にとって非常に紛らわしいタイプエラーを引き起こしています:
File "src/incremental.ml", line 110, characters 52-53:
Error: This expression has type string but an expression was expected of type
string
This instance of string is ambiguous:
it would escape the scope of its equation
これは私のレベルを少し上回っています!上記でやろうとしたことができない理由を理解していると確信しています。しかし、私は私の代替手段が何であるかを理解していません。実際、Menhir のマニュアルでは、この複雑さについて具体的に言及しています。
v
この関数を使用して、スタック要素のセマンティック値にアクセスできますElement (s, v, _, _)
。実際、シンボル の大文字と小文字を区別するとincoming_symbol s
、型に関する情報が'a
得られるため、値を使用して何か有用な処理を行うことができますv
。
わかりましたが、それは私がやったと思ったことです、上記: match
on 'ingによるケース分析、単一の特定のタイプincoming_symbol s
のケースを引き出します: 。v
string
tl;dr: この GADT から文字列ペイロードを抽出し、それを使って何か役に立つことをするにはどうすればよいですか?