Ocaml 使用Camlp4解析一组通用量词和存在量词

Ocaml 使用Camlp4解析一组通用量词和存在量词,ocaml,camlp4,Ocaml,Camlp4,我使用Camlp4解析一个量词字符串,其中量化关键字和变量用逗号分隔。一个例子如下: exists x,y,z, forall a,b, exists h,k 这里,存在和因为所有都是关键字,x、y、z、a、b、h、k都是标识符。相应的令牌是存在,用于所有和字符串标识符 我的数据结构: type quantifier = | Exists of string | Forall of string 要分析上面的量词字符串,我的规则是: id: [[ `IDENTIFIER s-&g

我使用Camlp4解析一个量词字符串,其中量化关键字和变量用逗号分隔。一个例子如下:

exists x,y,z, forall a,b, exists h,k
这里,
存在
因为所有
都是关键字,
x、y、z、a、b、h、k
都是标识符。相应的令牌是
存在
用于所有
字符串标识符

我的数据结构:

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])").
你知道如何解决这个问题吗?当
`COMMA
是关键字之后检测到元素时,如何使
LIST1
停止抛出错误

多谢各位

(更多信息,如果我使用空格分隔受同一量化关键字影响的变量,如
exists x y z,forall a b,exists h k
。并删除
one\u kind\u quantifiers
规则中的
SEP`COMMA
,那么解析器可以完美地解析这个新字符串)

===========================

更新解决方案:

根据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
]];

编写
id\u列表
规则的第二种方法会引发与使用
LIST1
时相同的错误。(因此,我猜可能是
LIST1
的实现方式…

camlp4是递归下降解析器,IIRC它将仅在每个规则的第一个标记上回溯,一旦第一个标记匹配,它将继续到规则结束。在本例中,对于
LIST1
,它可以在逗号上匹配,因此它会下降,但第二个标记并不像预期的那样,而且回溯太晚了。我想展开
LIST1
并将其内联到语法中可以解决这个问题,但可能会非常难看。

谢谢Igor的建议!是的,你说得对!通过展开列表1,我能够按预期编写解析器。我在主线程中更新了解决方案。