问题标签 [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,并相应地选择一个延续:- 如果在使用输入时解析
swithn成功,请cok继续。 s如果使用输入时with的解析n失败,请cerr继续。s如果with的解析成功而没有消耗输入,请遵循从 派生n的延续:neokeokneok y s' err' = eok y s' (mergeError err err')s如果with的解析失败而没有消耗输入,请遵循从 派生n的延续:neerreerrneerr y s' err' = eerr (mergeError err err')
- 如果在使用输入时解析
我的问题是:
为什么我们在跟随“空”延续而不是跟随“消耗”延续时合并错误,从而忘记所有先前的错误?
这一定是一个设计决定,但我无法弄清楚它背后的原因。也许有一个简单的例子可以澄清这一点?
parsing - 在算术表达式中解析表达式
我想解析算术表达式。
这是我当前的解析器:
使用它我可以正确解析:
像这样生成 AST。
我可以解析的另一件事是通用表达式。这些可以是变量、方法调用、三元组等。
例如
身份标识:
这会产生:
方法调用:
这会产生:
这是解析通用表达式的示例。
这很好用,但我也想在其中解析算术表达式。
这意味着使用expressionParserI 现在可以解析所有不同的表达式,包括算术表达式。如果它恰好是一个算术表达式,它会被包裹在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,特别是如果我能找到现成的解析器。