问题标签 [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.
parsing - 基于令牌的内容在解析器杠杆处进行分支
我正在为一个小项目开发一个简单的示例解析器/词法分析器,但我遇到了一个问题。
我正在按照以下方式解析内容:
... 、 或空格中的任何SEP
一个(但不是多个!)在哪里。|
,
现在,我不想将字段顺序锁定在词法分析器顺序中,因此我尝试使用一组非常简单的标记来对此进行词法分析:
现在,如果gender
字段不包含一小组预先确定的值,例如{male,female,neither,unspecified}
. 我可以包装解析器并处理这个问题,但我真的很想将此要求编码到自动机中以供将来扩展。
我的第一次尝试,看起来像这样,可怕地失败了:
是的,没有骰子。显然,我对非结构化词法分析的尝试已经很糟糕了。
解析这样的东西的惯用方法是什么?
parsing - 为什么我的 EOF / linebreak 非终结符总是发生 shift/reduce 冲突?
因此,在将解析语法放在一起时,我仍然很初级。当我有轮班减少冲突时,我需要帮助剖析 Menhir 报告的冲突。
以这个小语法为例:
Menhir 的--explain
标志产生了对由此产生的移位/减少冲突的描述。不幸的是,我无法确定它的正面或反面:
我花了一个晚上试图通过文档来挖掘 shift/reduce 冲突实际上是什么,但我不得不承认我很难理解我正在阅读的内容。有人可以给我一个关于移位/减少冲突的简单(好吧,尽可能多地)解释吗?具体使用上述示例的上下文?
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 的期望。
parsing - 解析先前列表时的歧义
在使用 Menhir 编写解析器代码时,我不断遇到这种设计模式,这变得非常令人沮丧。我正在尝试构建一个接受“a*ba”或“bb”的解析器。为此,我使用以下语法(注意A*
与 相同list(A)
):
但是,此代码无法解析字符串“ba”。menhir 编译器还指出解析器中存在 shift-reduce 冲突,具体如下:
所以| B A
需要一个转变,而| A* B A
当第一个标记是时需要一个减少B
。我可以手动解决这种歧义,并通过将表达式更改为如下所示来获得预期的行为(注意A+
与 相同nonempty_list(A)
):
在我的印象中,exp
和exp2
读法一样,但显然区别对待。有没有办法在exp
没有代码重复的情况下编写我想要的东西(这可能会导致其他问题)?这是我应该完全避免的设计模式吗?
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 节)为此提供了更多工具。'a
s
'a lr1state
s
好,爽!所以我开始深入检查 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 中提取字符串有效负载,并用它做一些有用的事情?
ocaml - 从 OCaml 词法分析器获取令牌
我目前正在开发基于终端的文本编辑器。我想为在文本编辑器中打开的 .ml 文件支持一种语法高亮显示。我在想,如果有一种方法可以访问通常用于 OCaml 的词法分析器,那么也许我可以使用该词法分析器对从 .ml 文件中读取的文本进行适当的着色。
这可能吗?
parsing - Menhirget 区间之间的值
我在 parser.mly 中得到了这条规则:
我需要将 [start .. end] 的值传递给 list "l"。示例([1..4])。我手动搜索,separated_list(TWOPoints, intervalue)
只得到值 1 和 4。但我需要 1 到 4 之间的所有值,包括像这样的 [1..2..3..4],但不必详尽无遗。
ocaml - 在 OCaml Menhir 中,如何为 C++/Rust/Java 风格的泛型编写解析器
在 C++ 中,一个著名的解析歧义发生在如下代码中
如果T
是一个类型,它就是它的样子(a
类型变量的声明x<T>
,否则它是(x < T) > a
(<>
比较运算符,不是尖括号)。
事实上,我们可以进行更改以使其变得明确:我们可以使<
和>
非关联。所以x < T > a
,如果没有括号,即使x
,T
并且a
都是变量名,也不会是一个有效的句子。
如何解决孟希尔的这场冲突?乍一看,我们似乎做不到。即使进行了上述修改,我们也需要在看到另一个 close 之前先查看不确定数量的标记>
,并得出结论它是模板实例化,否则,得出结论它是一个表达式。Menhir 有什么方法可以实现这种任意的前瞻吗?
parsing - 使用 OCaml Menhir,有没有办法在处理之前访问某些内容?
我正在编写一个解析器来解析和计算计算器中的函数导数。
我在执行产品和商规则时遇到了问题:对于产品,推导公式是 (u*v)' = u'v+uv',因此我需要最终输出中的 u 和 u' 的值。使用我目前拥有的解析器,每当需要写 u 时,它已经被 u' 取代,我完全不知道如何保存它的值,甚至是否可能......
这是解析器:
PS:我知道它可能根本不是最好的语法定义,它仍在进行中
parsing - 在确定标记之前让词法分析器考虑解析器?
我正在 ocamllex 和 ocamlyacc 中编写一个词法分析器和解析器,如下所示。function_name
和table_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 }
。但是,我想知道是否还有其他选择。难道不能让词法分析器和解析器一起工作来确定标记和减少吗?