问题标签 [megaparsec]
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.
haskell - parsec 如何递归解析简单表达式?
我有这样的字符串:***
, **(*)*
,****(**(**)*)**
我想像这样在数据结构中解析它:
data Tree = Node [S] Tree Tree | Empty
在哪里
(S
并不意味着任何字符,它只是星号)*
*
我尝试构建解析器(我使用megaparsec
但它与 habitual 非常相似parsec
):
但它不起作用。我尝试了很多方法,但无法与之抗争。
haskell - Megaparsec:没有由 do 语句引起的 (ErrorComponent Void) 实例
我正在尝试使用 megaparsec 编写一个简单的解析器并遇到以下问题:
我在线收到错误消息:满足 .... 那说:
没有由 do 语句产生的 (ErrorComponent Void) 实例在“do”块的 stmt 中:满足(notElem
“!>”)
haskell - 在Haskell中定义了一个类型类的名字后,函数后面的竖线是什么意思?
我正在查看megaparsec
库并注意到一个类被定义为
我知道我正在创建一个名为 MonadParsec 的类型类,但究竟是什么| m -> e s
意思?
parsing - Megaparsec:使用 try 时出现意外的输入消耗
我目前正在使用 megaparsec 库在 Haskell 中编写我的简单编程语言解析器。
我找到了这个megaparsec 教程,并编写了以下解析器代码:
具有保留名称错误处理的简单标识符解析器。它成功解析有效标识符,例如foo
, bar123
。
但是当无效输入(又名保留名称)进入解析器时,它会输出错误:
其中,错误消息还可以,但是错误位置(1:3:
)与我的预期有点不同。我预计错误位置是1:1:
.
在定义的以下部分中identifier
,
如果失败并返回源位置,我预计try
会表现得像没有消耗输入。(p >>= check)
1:1:
我的期望错了吗?我怎样才能让这段代码按我的预期工作?
parsing - megaparsec 在解析错误时报告不正确的位置
对于这个项目,我分两个阶段进行解析。第一阶段处理 include/ifdef/define 指令并将输入分成[Span]
项目,这些项目在原始输入中定义它们的起点/终点以及正文。然后第二阶段将此流解析为我的 AST 以进行后续处理。
AST 的每个元素都带有它的源位置,并且在解析后捕获的任何语义错误都会打印正确的错误位置,而不管包含深度如何。这部分至关重要,因为它出现在出现问题的阶段之后。
该问题在第二阶段从包含的文件中给出了一个解析错误,它报告了一个虚假错误,其位置位于输入的顶级规则中。初始文件中的解析错误可以正常工作。任何指令的存在甚至会将初始文件分成多个块,因此这不是“单个块”与“多个块”的问题。
鉴于 AST 正在获取正确的位置这一事实,我很难理解 Megaparsec 在遇到解析错误时如何报告错误信息。
我包含了我的流实例和 (set|get)(Position|Input) 代码,因为这些看起来像是相关的位。我觉得一定有一些我没有做的兆秒内务处理,或者我的 Stream 实例由于某种原因无效。
找到包含并交换它:
如果我们到达输入弹出堆栈的末尾并继续:
haskell - 通过延续传播(Mega)Parsec 错误
我对(Mega)Parsec 的内部运作有一个有点技术性的问题,其非正式的上下文是:
通过 continuation 控制错误消息的累积/传播的想法是什么
Parsec
?
具体来说:考虑mplus
制作ParsecT
. MonadPlus
( source )
mplus m n
将要解析的字符串作为输入,并根据解析的结果s
继续cok
, cerr
, eok
, 和eerr
跟随。
s
首先解析m
:
- 如果解析成功并消耗(分别不消耗)的一部分
s
,则遵循cok
(分别eok
)继续。 s
如果在使用 的部分时with的解析m
失败s
,请cerr
继续。s
假设with的解析m
失败而没有消耗任何东西;让err
成为与此失败相关的解析错误。s
然后我们尝试用解析n
,并相应地选择一个延续:- 如果在使用输入时解析
s
withn
成功,请cok
继续。 s
如果使用输入时with的解析n
失败,请cerr
继续。s
如果with的解析成功而没有消耗输入,请遵循从 派生n
的延续:neok
eok
neok y s' err' = eok y s' (mergeError err err')
s
如果with的解析失败而没有消耗输入,请遵循从 派生n
的延续:neerr
eerr
neerr y s' err' = eerr (mergeError err err')
- 如果在使用输入时解析
我的问题是:
为什么我们在跟随“空”延续而不是跟随“消耗”延续时合并错误,从而忘记所有先前的错误?
这一定是一个设计决定,但我无法弄清楚它背后的原因。也许有一个简单的例子可以澄清这一点?
parsing - 在算术表达式中解析表达式
我想解析算术表达式。
这是我当前的解析器:
使用它我可以正确解析:
像这样生成 AST。
我可以解析的另一件事是通用表达式。这些可以是变量、方法调用、三元组等。
例如
身份标识:
这会产生:
方法调用:
这会产生:
这是解析通用表达式的示例。
这很好用,但我也想在其中解析算术表达式。
这意味着使用expressionParser
I 现在可以解析所有不同的表达式,包括算术表达式。如果它恰好是一个算术表达式,它会被包裹在AExprAsExpr
.
问题
我想解析包含其他表达式的算术表达式。
例如
为此,我最初的想法是更改算术解析器,以便它也解析表达式。
问题在于aTerm
调用表达式解析器时存在递归循环,表达式解析器调用aExpr
. 这会导致无限循环。还有一个问题是所有identifiers
现在都将被包裹在一个AExprAsExpr
.
在算术表达式中解析表达式的正确方法是什么?
parsing - Haskell Parsec、MegaParsec 或 Happy 的简单 C 语法
我开发了一个预处理器,将 C 语句的子集转换为 gcc _asm 语句。对于这个项目,我很乐意重用使用任何流行的 Haskell 技术编写的现有 C 语句解析器,或者只是从一些简单的 C 子集解析器开始以避免重做现有工作。
不幸的是,到目前为止,我发现除了 C 之外的所有语法。虽然我可以从 Java/Go 的 Parsec 语法开始,但似乎 MegaParsec 是更好的选择?
我可以快速开发小的 C 子集的语法,但是对于较大的 C 子集的即用型语法将允许我完全跳过 C 语句解析器的开发,而专注于项目的核心 - asm 代码生成。
最终,它可能会变成 C++ 代码的 LLVM pass 转译部分,但为了快速原型,我更喜欢 Haskell,特别是如果我能找到现成的解析器。