问题标签 [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 回答
280 浏览

regex - 如何将这个正则表达式转换为 Megaparsec 解析器而不造成混乱?

考虑这个正则表达式:

如果我运行它foo/bar/baz=one,two,它匹配并且子组捕获one。如果我运行它foo/bar/baz/bar/baz=three,four,five,它匹配并且子组捕获three,four

我知道如何把它变成regex-applicative解析器或ReadP解析器:

这两个都按照我想要的方式工作。但是当我尝试将其直接音译成 Megaparsec 时,它变得很糟糕:

我知道这源于 Megaparsec 默认情况下不回溯。我试图通过坚持try在一堆不同的地方来解决这个问题,但我无法让它发挥作用。最终,我得到了这个怪物notFollowedBy

但这看起来像一团糟!特别是,我不喜欢我实际上必须两次指定大部分模式。从技术上讲,这不等于 regex ^foo/(?:[^=/]|/(?!baz=))+/baz=((?:.(?![^,]*$))*),[^,]*$,而不是我最初的 regex 吗?必须有更好的方法来编写该解析器。我该怎么做?


编辑:我也尝试过这种方式,它也有效(不,它错误地接受foo//baz=,):

不过,它看起来一样混乱,这manyTill意味着它不再真正映射到任何正则表达式。

0 投票
1 回答
49 浏览

haskell - stack runghc 与 stack ghci Haskell 产生的不同结果

我正在使用 Megaparsec 编写解析器。基本上,主文件将打开并读取文件的内容,然后解析该内容。在 ghci 中运行主文件时,一切都正确生成 img-1

但是当我尝试使用堆栈 runghc -- app/Main.hs 运行主文件时,发生了奇怪的解析错误: img-2

这是 GitHub 上的项目:https ://github.com/phuongduyphan/dbml-parser-haskell

某人可以看看并告诉我我做错了什么吗?为什么运行相同的 main 函数会导致堆栈 ghci 和堆栈 runghc 的输出不同?

0 投票
2 回答
180 浏览

parsing - Haskell - 用另一个解析器散布解析器

我有两个解析器parser1 :: Parser aparser2 :: Parser a.

我现在想解析一个a穿插它们的 s列表parser2

所需的签名类似于

例如,如果Parser a解析'a'字符并Parser b解析'b'字符,那么interspersedParser应该解析

我正在使用megaparsec。是否已经有一些行为像这样的组合器,我目前无法找到?

0 投票
1 回答
151 浏览

parsing - 避免使用 `sepBy` 解析最后一个分隔符

我正在尝试使用megaparsec.

其中一部分是由分隔符分隔的字符串的重复,我正在使用sepBy它。考虑例如

这可以正确解析,,,,""..."a"如果"asa"我需要继续使用另一个以我的分隔符开头的解析器进行解析,则会出现问题,如

如果我尝试"asasomething"使用此解析器解析字符串,我希望得到("aa", "something"). 相反,我收到一个错误,因为我没有aafter the second s

我也试过了,sepEndBy但结果是一样的

0 投票
0 回答
99 浏览

haskell - Megaparsec:嵌套缩进块吃太多

我在嵌套缩进块吞下新行时遇到问题。我想解析一个函数定义(或者更确切地说跳过整个主体,func.def.不一定是顶级的)。

例子:

我的代码:

pFuncHead,pStatement并且pSomeTillEol不要使用尾随的新行(只是scn这样做,我使用本教程作为模板)。

跑了"func m():\n pass\n\n"

为什么是pMultiline,所以我猜indentBlock,吃掉尾随的新行?如何解决?

0 投票
1 回答
96 浏览

haskell - 如何在通过解析器组合器(makeExprParser)库调用函数后正确解析字段访问?

我想解析这样的表达式:a().x. 它应该看起来像EAttrRef (EFuncCall (EVarRef "a") []) "x"。不幸的是,我的表达式解析器停止得太快了,它只会解析a()然后停止。

代码:

调试输出:

在我看来,这makeExprParser不是opFuncCall第二次调用(与索引访问调试输出的外观相比),但我不知道为什么不调用。

当我降低opAttrRef优先级时它会解析,但随后会产生错误的树(例如,正确的操作数x.a()a()不正确的,应该是a,然后整个认为应该在函数调用中),所以我不能使用它(我很确保当前优先级是正确的,因为它基于该语言的参考)。

0 投票
1 回答
249 浏览

haskell - Why doesn't "between (char '"') (char '"') (many charLiteral)" work for parsing string literals?

The documentation for Text.Megaparsec.Char.Lexer.charLiteral suggests using char '"' *> manyTill charLiteral (char '"') for parsing string literals (where manyTill is defined in the module Control.Applicative.Combinators in the parser-combinators library).

However, Control.Applicative.Combinators also defines between, which -- as far as I can see -- should do the same as the above suggestion when used like so: between (char '"') (char '"') (many charLiteral).

However, using the between parser above does not work for parsing string literals -- failing with "unexpected end of input. expecting '"' or literal character" (indicating that the ending quote is never detected). Why not?

Also, more generally, why isn't between pBegin pEnd (many p) equivalent to pBegin *> manyTill p pEnd?

0 投票
1 回答
307 浏览

parsing - 使用 megaparsec 正确解析嵌套数据

我正在尝试更熟悉 megaparsec,但我遇到了一些关于presedences 的问题。通过标题中的“嵌套数据”,我指的是我正在尝试解析类型,而这些类型又可能包含其他类型。如果有人可以解释为什么这不符合我的预期,请不要犹豫告诉我。

我正在尝试解析类似于 Haskell 中的类型。类型要么是基本类型Int,要么BoolFloat类型变量a(任何小写单词)。我们还可以从类型构造函数(大写单词)构造代数数据类型,例如Maybe类型参数(任何其他类型)。例子是Maybe aEither (Maybe Int) Bool。与右侧关联并用 构造的函数->,例如Maybe a -> Either Int (b -> c). N 元元组是由 and 分隔,并包含在(and中的类型序列),例如(Int, Bool, a). 类型可以用括号括起来以提高其优先级(Maybe a)()还定义了单位类型。

我正在使用这个 ADT 来描述这一点。

我试图编写一个megaparsec解析器来解析这些类型,但我得到了意想不到的结果。我附上下面的相关代码,之后我将尝试描述我的经历。

这可能是压倒性的,所以让我解释一些关键点。我知道我有很多不同的结构可以匹配左括号,所以我将这些解析器包装在 中try,这样如果它们失败,我可以尝试下一个可能消耗左括号的解析器。也许我用try的太多了?可能回溯这么多会影响性能吗?

我还尝试通过定义一些术语和运算符表来制作表达式解析器。但是,您现在可以看到我已经注释掉了运算符(功能箭头)。正如代码现在看起来一样,当我尝试解析函数类型时,我会无限循环。我认为这可能是因为当我尝试解析函数类型(从 调用pType)时,我立即尝试解析表示函数域的类型,它再次调用pType. 我将如何正确地做到这一点?

如果我决定改用运算符表,而不使用我的自定义解析器来处理函数类型,我会使用错误的优先级来解析事物。例如Maybe a -> b被解析为Maybe (a -> b),而我希望它被解析为(Maybe a) -> b. 有没有一种方法可以让我使用运算符表并且仍然让类型构造函数比函数箭头绑定得更紧密

最后,当我边走边学时,如果有人看到任何误解或奇怪/意外的事情,请告诉我。我已经阅读了教程的大部分内容以达到这一点。

请让我知道我可以进行的任何编辑以提高我的问题的质量!

0 投票
1 回答
138 浏览

haskell - 可以在 Haskell 中以纯代码读取文件吗?

我正在为 DSL 编写编译器。将源文件读入字符串后,其余所有步骤(解析、类型检查和代码生成)都是纯代码,将代码从一种表示形式转换为另一种表示形式。一切都很好,直到源文件中存在依赖项(想想 中的#include预处理器C)。解析器需要读取依赖文件并递归解析它们。这使它不再纯粹。我必须将其从返回更改ASTIO AST. 此外,所有后续步骤(类型检查和代码生成)也必须返回 IO 类型,这需要进行重大更改。在这种情况下,处理读取依赖文件的好方法是什么?

ps我可以使用unsafePerformIO,但这似乎是一个可能导致技术债务的hacky解决方案。

0 投票
1 回答
46 浏览

parsec - 为什么解析器中的“可选”会出错

https://github.com/complyue/dcp是重现此错误的最小工作示例

我相信它optionalSemicolon导致了失败:

https://github.com/complyue/dcp/blob/1df7ad590d78d4fa9a017eb53f9f265e291bdfa7/src/Parser.hs#L50-L54

它的定义是这样的: https ://github.com/complyue/dcp/blob/1df7ad590d78d4fa9a017eb53f9f265e291bdfa7/src/Parser.hs#L31-L32

我无法解释为什么它会像这样失败。