问题标签 [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.

0 投票
1 回答
439 浏览

parsing - 用 foldLine 解析许多块

对于这个简化的问题,我试图解析一个看起来像

进入

我试过的代码如下:

这适用于一个块items

但是,一旦我尝试 parse many items,它就会在第一条未缩进的行上失败:

或者,使用更简单的输入:

0 投票
1 回答
270 浏览

parsing - 表达式树的缩进感知解析

作为这个问题的后续,我现在正在尝试解析具有变量和case ... of ...表达式的表达式语言。语法应该是基于缩进的:

  • 表达式可以跨越多行,只要每一行都相对于第一行缩进即可;即这应该被解析为单个应用程序:

    /li>
  • 表达式的每个替代项都case需要在自己的行上,相对于case关键字缩进。右侧可以跨越多条线。

    应该被解析成一个case有两种选择的单一的,用xf x y作为右手边

我已将代码简化为以下内容:

如您所见,我正在尝试使用此答案中的技术来将具有比关键字缩进更多alt的 ace 的替代词分开。sp'case

问题

这似乎适用于仅由应用程序组成的单个表达式:

它不适用于使用链接答案中的技术列出此类表达式:

case尝试使用行折叠时,表达式失败了:

case最外层表达式无需折线即可工作,仅适用于一种选择:

但是case一旦我有多个alt替代品就会失败:

我究竟做错了什么?

0 投票
1 回答
79 浏览

parsing - 是否可以强制回溯所有选项?

我需要为函数声明解析这个语法

我写了这个解析器

我可以解析foo (x) = 1但我无法解析foo x = 1

我知道它会尝试解析此代码Func "foo" (Label "x" 1)并失败。但是在失败之后为什么它不能尝试解析它Func "foo" (Ident "x") = 1

有什么办法吗?

我也尝试过交换identparamLabel

在这种情况下,我可以解析foo x = 1但我无法解析foo (x = 1) = 2

0 投票
2 回答
199 浏览

parsing - 用 Parsec 分组线

我有一个基于行的文本格式,我想用Parsec† 解析。一行要么以井号开头并指定以冒号分隔的键值对,要么是前面标记描述的 URL。

这是一个简短的示例:

为简单起见,我将所有内容存储为String. 一个标签是一个type Tag = (String, String),例如("foo", "bar")。最终,我想将这些分组为([Tag], URL).

但是,我很难弄清楚如何解析 [一个或多个标签] 或 [一个 URL]。

我目前的方法如下所示:

如果我尝试在上面的示例上运行它,我会收到如下解析错误:

显然我的many结合使用<|>是不正确的。由于标签解析器不会使用来自 URL 解析器的任何输入,因此它与回溯无关。我需要如何更改才能获得所需的结果?

完整示例可在GitHub上找到。


† 我实际上在这里使用 MegaParsec 来获得更好的错误消息,但我认为这个问题非常普遍,与解析器组合器的任何特定实现无关。

0 投票
0 回答
243 浏览

haskell - Megaparsec:解析期间的宏扩展

在一个小型 DSL 中,我正在解析宏定义,类似于#defineC 预处理器指令(这里是一个简单的示例):

当解析器遇到以下调用时

它扩展到

我目前的做法是:

  • 将解析器包装在 State monad 中
  • 解析宏定义时,将它们存储在状态中,其主体未解析(将其解析为字符串)
  • 解析宏调用时,在状态中找到定义,替换正文中的参数,用此正文替换调用并继续解析。

最后一步的一些代码:

这种方法做得很好。但是,它有许多缺点。

多次解析

任何有效的 DSL 表达式都可以是宏调用的参数。因此,即使我只需要它们的文本表示(在宏体中被替换),我也需要解析它们然后再次将它们转换为字符串——仅仅寻找下一个逗号是行不通的。然后将解析完整和自定义的宏。所以在实践中,宏参数被解析两次(并且也被显示,这有它的成本)。此外,每次调用都需要对(几乎相同的)主体进行新的解析。将正文保留在内存中的原因是为了允许最大的灵活性:在正文中,甚至 DSL 关键字也可以从宏参数中构造出来。

错误处理

因为展开的主体插入在未使用的输入之前(替换调用),所以初始输入和最终输入可能完全不同。在解析错误的情况下,扩展中发生错误的位置输入可用。但是,在处理错误时,我只有原始输入,而不是扩展输入。所以错误位置将不匹配。这就是为什么在上面的代码片段中,我使用状态来保存扩展的输入,以便在解析器因错误退出时可用。这很好用,但我注意到它变得非常昂贵,每次扩展时都会为整个流分配新的文本数组(输入流是文本)。也许在这种情况下将扩展输入保持为字符串而不是文本会更便宜,即当需要更换中间部分时?

这个问题的原因是:

  • 我将不胜感激对上述两个问题的建议/评论
  • 任何人都可以提出更好的方法吗?
0 投票
1 回答
133 浏览

haskell - 使用 megaparsec 不同位置的多个错误

我将使用 megaparsec 来解析大学项目的编程语言。但是,我寻找一种方法来报告多个错误。

我知道 withRecovery 并且我看到了这个问题,但我没有发现在不同位置发生错误的情况。

例如在这个java代码中:

有error1“第3行第10列的预期类型”和error2“第5行第22列缺少分号”

我知道我可以将错误消息与failure多个位置结合起来,但是呢?我怎么做 ?

0 投票
2 回答
512 浏览

haskell - Megaparsec,使用 StateT 和 ParsecT 回溯用户状态

使用 Megaparsec 5。按照本指南StateT,我可以通过组合和来实现回溯用户状态ParsecT(未定义的类型应该是显而易见的/不相关的):

如果我运行解析器p :: MyParser a,如下所示:

的类型parsed是:

这意味着,如果出现错误,用户状态将丢失。

有没有办法在这两种情况下都有它?

编辑: 如果出现错误,我是否可以使用自定义错误组件而不是 Dec(5.0 中引入的功能)并将用户状态封装在那里?

0 投票
1 回答
543 浏览

haskell - 使用开始和结束符号使用 Megaparsec 解析块注释

我想使用 Megaparsec 在 Haskell 中解析与此类似的文本。

, where# START SKIP# END SKIP标记要解析的文本块的开始和结束。

skipBlockComment相比,我希望解析器返回开始和结束标记之间的行。

这是我的解析器。

skip解析器按预期工作。

为了在开始和结束标记内允许可变数量的空白,例如,# START SKIP我尝试了以下操作:

用于skip'解析上述文本会出现以下错误。

我想了解此错误的原因以及如何修复它。

0 投票
0 回答
464 浏览

haskell - 如何在 Megaparsec 中解析字符串文字?

所以我花了一些时间阅读文档,但除了最基本的语言之外,教程还不够,而且很难通读该语言的整个文档。我太容易迷路了。

我将如何创建"&"#someStringUtf8"解析器?

charLiteral仅适用于 ASCII 字符还是支持任何类型的 UTF8 字符(数字等)?

0 投票
1 回答
192 浏览

haskell - 我可以轻松地将 attoparsec 包装在变压器中吗?

我想编写代码来做类似 C 预处理的事情。所以我寻找图书馆并得到了两个候选人attoparsec,, megaparsec.

我需要功能报告错误位置并且megaparsec已经有了。但是attoparsec对于性能来说是可取的。

如果我将错误位置功能添加到attoparsec's Parsermonad,那么我是否必须将其包装在StateT变压器中并在使用它们时提升所有库的功能?我觉得工作很累。有没有更好的方法?

编辑

我将采用megaparsec适合这种情况的方法。但我仍然想知道如何包装attoparsec's Parsermonad。有没有人可以告诉我上面提到的方法是否是最好的方法?

我只想知道单子包装方法。换句话说,是否解除所有内部 monad 函数是唯一的解决方案。