首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用foldLine解析多个块

用foldLine解析多个块
EN

Stack Overflow用户
提问于 2016-05-16 14:27:15
回答 1查看 470关注 0票数 3

对于这个简化的问题,我试图解析如下所示的输入

代码语言:javascript
复制
foo bar
 baz quux 
 woo
hoo xyzzy 
  glulx

转到

代码语言:javascript
复制
[["foo", "bar", "baz", "quux", "woo"], ["hoo", "xyzzy", "glulx"]]

我尝试过的代码如下:

代码语言:javascript
复制
import qualified Text.Megaparsec.Lexer as L
import Text.Megaparsec hiding (space)
import Text.Megaparsec.Char hiding (space)
import Text.Megaparsec.String
import Control.Monad (void)
import Control.Applicative

space :: Parser ()
space = L.space (void spaceChar) empty empty

item :: Parser () -> Parser String
item sp = L.lexeme sp $ some letterChar

items :: Parser () -> Parser [String]
items sp = L.lineFold sp $ \sp' -> some (item sp')

items_ :: Parser [String]
items_ = items space

这适用于一个块items

代码语言:javascript
复制
λ» parseTest items_ "foo bar\n baz quux\n woo"
["foo","bar","baz","quux","woo"]

但是,一旦我试图解析many items,它就会在第一个未缩进的行上失败:

代码语言:javascript
复制
λ» parseTest (many items_) "foo bar\n baz quux\n woo\nhoo xyzzy\n  glulx"
4:1:
incorrect indentation (got 1, should be greater than 1)

或者,用一个更简单的输入:

代码语言:javascript
复制
λ» parseTest (many items_) "a\nb"
2:1:
incorrect indentation (got 1, should be greater than 1)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-16 18:19:26

Megaparsec的作者是这样的:-)当你使用Megaparsec时,要记住的一件事是,它的lexer模块实际上是“低级”的。它不会做任何你无法构建自己的事情,也不会将你锁在任何特定的“框架”中。因此,在您的情况下,您有为您提供的空间使用者sp',但是您应该谨慎使用它,因为当您的缩进级别小于或等于整个折叠开始时的缩进级别时,它肯定会失败,顺便说一句,这就是折叠结束的方式。

引用医生们

创建一个支持行折叠的解析器。第一个参数用于使用行折叠组件之间的空白,因此它必须使用新行才能正常工作。第二个参数是一个回调,它接收自定义的空间消耗解析器作为参数。此解析器应在可以放置在不同行上的行折叠的单独组件之后使用。

代码语言:javascript
复制
sc = L.space (void spaceChar) empty empty

myFold = L.lineFold sc $ \sc' -> do
  L.symbol sc' "foo"
  L.symbol sc' "bar"
  L.symbol sc  "baz" -- for the last symbol we use normal space consumer

行折叠不能无限期地运行,因此您应该期望它会失败,错误消息类似于您现在拥有的错误消息。要想成功,你应该想个办法让它完成。这通常是通过在行折叠的末尾使用“正常”空间消费者来完成的:

代码语言:javascript
复制
space :: Parser ()
space = L.space (void spaceChar) empty empty

item :: Parser String
item = some letterChar

items :: Parser () -> Parser [String]
items sp = L.lineFold sp $ \sp' ->
  item `sepBy1` try sp' <* sp

items_ :: Parser [String]
items_ = items space

item `sepBy1` try sp'运行到失败,然后sp抢占其余部分,因此可以解析下一个折叠。

代码语言:javascript
复制
λ> parseTest items_ "foo bar\n baz quux\n woo"
["foo","bar","baz","quux","woo"]
λ> parseTest (many items_) "foo bar\n baz quux\n woo\nhoo xyzzy\n  glulx"
[["foo","bar","baz","quux","woo"],["hoo","xyzzy","glulx"]]
λ> parseTest (many items_) "foo bar\n baz quux\n woo\nhoo\nxyzzy\n  glulx"
[["foo","bar","baz","quux","woo"],["hoo"],["xyzzy","glulx"]]
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37256316

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档