问题标签 [menhir]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
126 浏览

parsing - 基于令牌的内容在解析器杠杆处进行分支

我正在为一个小项目开发一个简单的示例解析器/词法分析器,但我遇到了一个问题。

我正在按照以下方式解析内容:

... 、 或空格中的任何SEP一个(但不是多个!)在哪里。|,

现在,我不想将字段顺序锁定在词法分析器顺序中,因此我尝试使用一组非常简单的标记来对此进行词法分析:

现在,如果gender字段不包含一小组预先确定的值,例如{male,female,neither,unspecified}. 我可以包装解析器并处理这个问题,但我真的很想将此要求编码到自动机中以供将来扩展。

我的第一次尝试,看起来像这样,可怕地失败了:

是的,没有骰子。显然,我对非结构化词法分析的尝试已经很糟糕了。

解析这样的东西的惯用方法是什么?

0 投票
1 回答
340 浏览

parsing - 为什么我的 EOF / linebreak 非终结符总是发生 shift/reduce 冲突?

因此,在将解析语法放在一起时,我仍然很初级。当我有轮班减少冲突时,我需要帮助剖析 Menhir 报告的冲突。

以这个小语法为例:

Menhir 的--explain标志产生了对由此产生的移位/减少冲突的描述。不幸的是,我无法确定它的正面或反面:

我花了一个晚上试图通过文档来挖掘 shift/reduce 冲突实际上什么,但我不得不承认我很难理解我正在阅读的内容。有人可以给我一个关于移位/减少冲突的简单(好吧,尽可能多地)解释吗?具体使用上述示例的上下文?

0 投票
1 回答
144 浏览

ocaml - Menhir:--external-tokens 似乎找不到 Tokens 模块

我有一个tokens.ml文件,里面有一个type token声明。我也有tokens.mli同样的type token说法。现在,我有一个parser.mly使用tokens.mly. 我想把我的令牌tokens.ml/mli和我的解析器放在parser.mly.

所以,我尝试使用命令编译我的解析器

这给了我一个错误,说我的一个令牌不存在。具体来说,

因此,menhir 没有找到该Tokens模块。我不知道如何使它对menhir. 我尝试创建一个tokens.cma库,但即便如此,我仍然会遇到同样的错误。

Menhir 似乎并不关心模块是否不存在,因为如果我运行命令

它仍然给出关于OPERATOR未定义的相同错误。

如何让 Menhir 找到我的令牌模块。我宁愿不使用 ocamlbuild。如果您建议使用 ocamlbuild 解决方案,请至少说明我可以执行的中间手动步骤。我想了解 Menhir 的期望。

0 投票
1 回答
124 浏览

parsing - 解析先前列表时的歧义

在使用 Menhir 编写解析器代码时,我不断遇到这种设计模式,这变得非常令人沮丧。我正在尝试构建一个接受“a*ba”或“bb”的解析器。为此,我使用以下语法(注意A*与 相同list(A)):

但是,此代码无法解析字符串“ba”。menhir 编译器还指出解析器中存在 shift-reduce 冲突,具体如下:

所以| B A需要一个转变,而| A* B A当第一个标记是时需要一个减少B。我可以手动解决这种歧义,并通过将表达式更改为如下所示来获得预期的行为(注意A+与 相同nonempty_list(A)):

在我的印象中,expexp2读法一样,但显然区别对待。有没有办法在exp没有代码重复的情况下编写我想要的东西(这可能会导致其他问题)?这是我应该完全避免的设计模式吗?

0 投票
1 回答
110 浏览

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

我正在尝试在生成的解析器中使用Menhir增量解析 API自省 API 。比如说,我想确定与特定 LR(1) 堆栈条目相关的语义值;即解析器先前使用的令牌。

给定一个抽象的解析检查点,封装在 Menhir 的 type'a env中,我可以从 LR 自动机中提取一个“堆栈元素”;它看起来像这样:

type 元素描述了 LR(1) 自动机堆栈中的一个条目。在形式的堆栈元素中Element (s, v, startp, endp)s是(非初始)状态并且v是语义值。该值v与状态的传入符号 A 相关联s。换句话说,值在进入v状态之前被压入堆栈s。因此,对于某些 type 'a, states有 type'a lr1state并且 valuev有 type 'a...

为了对值做任何有用的事情,必须通过检查状态v来获取有关类型的信息。到目前为止,类型是抽象的,所以没有办法检查. 检查 API(第 9.3 节)为此提供了更多工具。'as'a lr1states

好,爽!所以我开始深入检查 API:

类型 'a 终端是一种广义代数数据类型 (GADT)。'a 终端类型的值表示终端符号(没有语义值)。索引 'a 是与此符号关联的语义值的类型...

类型 'a 非终结符也是一个 GADT。'a 非终结符类型的值表示非终结符符号(没有语义值)。索引 'a 是与此符号关联的语义值的类型...

将这些拼凑在一起,我得到如下内容(其中“命令”是我的语法的非终结符之一,因此N_command是 a string nonterminal):

不幸的是,这对我来说是非常令人困惑的类型错误:

这有点超出我的水平!我很确定我明白为什么我不能做我上面试图做的事情;但我不明白我的选择是什么。事实上,Menhir 手册特别提到了这种复杂性:

此函数可用于访问v堆栈元素中的语义值Element (s, v, _, _)。事实上,通过对符号的案例分析incoming_symbol s,人们获得了关于类型的信息'a,因此获得了对值做一些有用的事情的能力v

好的,但这就是我认为我所做的,上面:通过match'ing on进行案例分析incoming_symbol s,拉出v单个特定类型的案例:string.

tl;博士:我如何从这个 GADT 中提取字符串有效负载,并用它做一些有用的事情?

0 投票
1 回答
52 浏览

ocaml - 从 OCaml 词法分析器获取令牌

我目前正在开发基于终端的文本编辑器。我想为在文本编辑器中打开的 .ml 文件支持一种语法高亮显示。我在想,如果有一种方法可以访问通常用于 OCaml 的词法分析器,那么也许我可以使用该词法分析器对从 .ml 文件中读取的文本进行适当的着色。

这可能吗?

0 投票
1 回答
64 浏览

parsing - Menhirget 区间之间的值

我在 parser.mly 中得到了这条规则:

我需要将 [start .. end] 的值传递给 list "l"。示例([1..4])。我手动搜索,separated_list(TWOPoints, intervalue)只得到值 1 和 4。但我需要 1 到 4 之间的所有值,包括像这样的 [1..2..3..4],但不必详尽无遗。

0 投票
2 回答
401 浏览

ocaml - 在 OCaml Menhir 中,如何为 C++/Rust/Java 风格的泛型编写解析器

在 C++ 中,一个著名的解析歧义发生在如下代码中

如果T是一个类型,它就是它的样子(a类型变量的声明x<T>,否则它是(x < T) > a<>比较运算符,不是尖括号)。

事实上,我们可以进行更改以使其变得明确:我们可以使<>非关联。所以x < T > a,如果没有括号,即使x,T并且a都是变量名,也不会是一个有效的句子。

如何解决孟希尔的这场冲突?乍一看,我们似乎做不到。即使进行了上述修改,我们也需要在看到另一个 close 之前先查看不确定数量的标记>,并得出结论它是模板实例化,否则,得出结论它是一个表达式。Menhir 有什么方法可以实现这种任意的前瞻吗?

0 投票
1 回答
81 浏览

parsing - 使用 OCaml Menhir,有没有办法在处理之前访问某些内容?

我正在编写一个解析器来解析和计算计算器中的函数导数。

我在执行产品和商规则时遇到了问题:对于产品,推导公式是 (u*v)' = u'v+uv',因此我需要最终输出中的 u 和 u' 的值。使用我目前拥有的解析器,每当需要写 u 时,它已经被 u' 取代,我完全不知道如何保存它的值,甚至是否可能......

这是解析器:

PS:我知道它可能根本不是最好的语法定义,它仍在进行中

0 投票
1 回答
51 浏览

parsing - 在确定标记之前让词法分析器考虑解析器?

我正在 ocamllex 和 ocamlyacc 中编写一个词法分析器和解析器,如下所示。function_nametable_name是相同的正则表达式,即只包含英文字母的字符串。确定字符串是否是function_name或是table_name检查其周围环境的唯一方法。例如,如果这样的字符串被[and包围],那么我们就知道它是 a table_name。这是当前代码:

lexer.mll,

parser.mly

正如我| function_name as s { FUNCTIONNAME s }之前写| table_name as s { TABLENAME s }的,上面的代码无法解析[haha];它首先在词法分析器中被认为haha是a function_name,然后在解析器中找不到任何对应的规则。如果它可以在词法分析器中被haha视为 a table_name,那么它将[haha]在解析器中匹配为表。

一种解决方法是在词法分析器中更精确。例如,我们在词法分析器中定义let table_name_with_brackets = '[' ['a'-'z' 'A'-'Z']+ ']'| table_name_with_brackets as s { TABLENAMEWITHBRACKETS s }。但是,我想知道是否还有其他选择。难道不能让词法分析器和解析器一起工作来确定标记和减少吗?