Camlp4 を使用して、量化キーワードと変数がコンマで区切られた量指定子の文字列を解析しています。一例を以下に示します。
exists x,y,z, forall a,b, exists h,k
ここで、exists
とforall
はキーワードでx,y,z,a,b,h,k
あり、識別子です。対応するトークンはEXISTS
、FORALL
およびIDENTIFIER of string
です。
私のデータ構造:
type quantifier =
| Exists of string
| Forall of string
上記の量指定子の文字列を解析するための私のルールは次のとおりです。
id: [[
`IDENTIFIER s-> s
]];
one_kind_quantifiers: [[
`EXISTS; il=LIST1 id SEP `COMMA -> List.map (fun v -> Exists v) il
|`FORALL; il=LIST1 id SEP `COMMA -> List.map (fun v -> Forall v) il
]];
quantifiers: [[
t=LIST0 one_kind_quantifiers SEP `COMMA -> List.flatten t
]];
ただし、私のパーサーは常にエラーをスローします。
Stream.Error("[id] expected after COMMA (in [one_kind_quantifiers])").
この問題を解決する方法を知っていますか? キーワードLIST1
の後に要素が検出されたときにエラーのスローを停止するにはどうすればよいですか?`COMMA
どうもありがとうございました!
(詳細については、空白を使用して、のような同じ量化キーワードの影響を受ける変数を区切ると、ルール内のexists x y z, forall a b, exists h k
を削除すると、パーサーはこの新しい文字列を完全に解析できます)。SEP `COMMA
one_kind_quantifiers
===========================
ソリューションの更新:
Igor (@ygrek) からの提案により、LIST1 を使用せずに手動で文字列のリストを解析するルールを作成することで、予想されるパーサーを作成することができました。
id_list: [[
`IDENTIFIER s -> [s]
|t=`id_list; `COMMA; `IDENTIFIER s -> t@[s]
]];
one_kind_quantifiers: [[
`EXISTS; il=id_list -> List.map (fun v -> Exists v) il
|`FORALL; il=id_list -> List.map (fun v -> Forall v) il
]];
quantifiers: [[
t=LIST0 one_kind_quantifiers SEP `COMMA -> List.flatten t
]];
文字列のリストを解析するルールは次のとおりです。
id_list: [[
`IDENTIFIER s -> [s]
| t=`id_list; `COMMA; `IDENTIFIER s -> t@[s]
]];
だがしかし:
id_list: [[
`IDENTIFIER s -> [s]
| `IDENTIFIER s; `COMMA; t=`id_list -> [s]@t
]];
ルールを記述する2 番目の方法ではid_list
、 を使用した場合と同じエラーがスローされますLIST1
。(だから私は多分それLIST1
が実装されている方法だと思います...)