Parsing 如何从GADT/存在类型的有效负载中提取有用信息?

Parsing 如何从GADT/存在类型的有效负载中提取有用信息?,parsing,ocaml,gadt,existential-type,menhir,Parsing,Ocaml,Gadt,Existential Type,Menhir,我试图在生成的解析器中使用的和。比如说,我想确定与特定LR1堆栈项相关联的语义值;i、 e.解析器以前使用过的令牌 给定一个抽象的解析检查点(封装在Menhir的“a env”类型中),我可以从LR自动机中提取一个“stack元素”;看起来是这样的: 类型元素= |元素:“a lr1state*”a*位置*位置->元素 type元素描述LR1自动机堆栈中的一个条目。在形式元素s、v、startp、endp的堆栈元素中,s是非初始状态,v是语义值。值v与状态s的输入符号A相关联。换句话说,值v在进

我试图在生成的解析器中使用的和。比如说,我想确定与特定LR1堆栈项相关联的语义值;i、 e.解析器以前使用过的令牌

给定一个抽象的解析检查点(封装在Menhir的“a env”类型中),我可以从LR自动机中提取一个“stack元素”;看起来是这样的:

类型元素= |元素:“a lr1state*”a*位置*位置->元素 type元素描述LR1自动机堆栈中的一个条目。在形式元素s、v、startp、endp的堆栈元素中,s是非初始状态,v是语义值。值v与状态s的输入符号A相关联。换句话说,值v在进入状态s之前被推到堆栈上。因此,对于某些类型“a”,状态s具有类型“a lr1state”,而值v具有类型“a…”

为了对值v做任何有用的事情,必须通过检查状态s来获得关于类型“a”的信息。到目前为止,a型LR1状态是抽象的,因此无法检查s。检验API§9.3为此提供了更多工具

好的,酷!因此,我开始深入研究检验API:

“a”型终端是广义代数数据类型GADT。“A终端”类型的值表示没有语义值的终端符号。索引“a”是与此符号关联的语义值的类型

类型uu端子= |单位终端 |T_B:int终端 类型“a非终结符”也是GADT。“A非终结符”类型的值表示没有语义值的非终结符符号。索引“a”是与此符号关联的语义值的类型

类型uu非终结符= |N_main:非终结的事物 将它们拼凑在一起,我得到了如下结果,其中command是语法的非终结符之一,因此N_command是字符串非终结符:

让当前_命令env:'a env= 让我记录一下= 匹配解释器。获取环境 |无->无 |一些解释器。元素lr1state,v,_startp,_endp-> 将解释器输入符号LR1状态与匹配 |解释器.N解释器.N_命令->一些v |_uf->i+1 在里面 f0 不幸的是,这给我带来了非常混乱的类型错误:

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手册特别提到了这种复杂性:

此函数可用于访问堆栈元素s、v、u、u中的语义值v。事实上,通过对输入符号s的案例分析,我们可以获得关于类型“a”的信息,因此我们可以利用值v做一些有用的事情

好的,但这就是我想我做的,上面:通过匹配传入的_符号s进行案例分析,拉出v是单个特定类型的案例:字符串


tl;dr:如何从这个GADT中提取字符串有效负载,并对其进行一些有用的操作?

如果您的错误听起来像

字符串的此实例不明确: 这将超出其等式的范围

这意味着类型检查器不能真正确定在模式匹配分支之外,v的类型应该是字符串,还是另一个等于字符串但仅在分支内部的类型。离开分支时,您只需添加类型注释即可消除这种歧义:

 | Interpreter.(N N_command) -> Some (v:string)