1

生成されたパーサーで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) は、この目的のためにさらにツールを提供します。'as'a lr1states

よし、かっこいい!そこで、インスペクション 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

わかりましたが、それは私がやったと思ったことです、上記: matchon 'ingによるケース分析、単一の特定のタイプincoming_symbol sのケースを引き出します: 。vstring

tl;dr: この GADT から文字列ペイロードを抽出し、それを使って何か役に立つことをするにはどうすればよいですか?

4

1 に答える 1