我正在使用Camlp4來解析量化關鍵字和變量之間用逗號分隔的一串量詞。一個例子是象下面這樣:使用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
。而在one_kind_quantifiers
規則刪除SEP `COMMA
,那麼解析器可以完全解析這個新的字符串)。
===========================
更新的解決方案:
與伊戈爾建議(@ ygrek),我可以通過不使用LIST1編寫預期的解析器,而是手動編寫規則來解析字符串列表。
id_list: [[
`IDENTIFIER s -> [s]
|t=`id_list; `COMMA; `IDENTIFIER s -> [email protected][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 -> [email protected][s]
]];
但不是:
id_list: [[
`IDENTIFIER s -> [s]
| `IDENTIFIER s; `COMMA; t=`id_list -> [s]@t
]];
寫id_list
規則的第二種方法拋出相同的錯誤時使用LIST1
。 (所以我猜這可能是LIST1
的實現方式......)
謝謝伊戈爾的建議!你是對的!通過展開LIST1,我可以按預期編寫解析器。我在主線程中更新瞭解決方案。 –