Parsing 生成一个解析器,该解析器在另一个解析器的输出上运行接收到的解析器,并以一元方式联接结果
给定以下类型和函数,用于将CSV字段的字段解析为字符串:Parsing 生成一个解析器,该解析器在另一个解析器的输出上运行接收到的解析器,并以一元方式联接结果,parsing,haskell,monads,monad-transformers,parsec,Parsing,Haskell,Monads,Monad Transformers,Parsec,给定以下类型和函数,用于将CSV字段的字段解析为字符串: type Parser resultType = ParsecT String () Identity resultType cell :: Parser String 我已经实现了以下功能: customCell :: String -> Parser res -> Parser res customCell typeName subparser = cell >>= either (cons
type Parser resultType = ParsecT String () Identity resultType
cell :: Parser String
我已经实现了以下功能:
customCell :: String -> Parser res -> Parser res
customCell typeName subparser =
cell
>>= either (const $ unexpected typeName)
return . parse (subparser <* eof) ""
customCell::String->Parser res->Parser res
customCell typeName子Parser=
细胞
>>=其中一个(常量$unexpected typeName)
返回。作语法分析(subparser遗憾的是,据我所知,Haskell没有一个解析器库或解析器生成器支持这样的垂直解析器组合。类似于您所写的内容,它已经非常好了。Dang!详细阐述@Daniel Wagner的答案……按照通常使用Parsec构建解析器的方式,您从解析特定c的低级解析器开始字符(例如,加号或数字),然后使用组合器(如many1
combinator,将读取单个数字的解析器转换为读取一个或多个数字的解析器,或将“一个或多个数字”后跟“加号”再后跟“一个或多个数字”的一元解析器)在其上构建解析器
然而,每个解析器,无论是低级数字解析器还是高级“加法表达式”解析器,都旨在直接应用于相同的输入流
您通常不做的是编写一个解析器,将输入流中的一块内容分解成一个字符串
,然后编写另一个解析器,对该字符串
(而不是原始输入流)进行解析,并尝试将它们组合起来。这是一种“垂直组合”Parsec并不直接支持这一点,它看起来不自然,也不是一元的
正如在评论中指出的,在某些情况下,垂直组合是最干净的总体方法(例如,当一种语言嵌入到另一种语言的组件或表达式中时),但它不是Parsec解析器通常采用的方法
应用程序中的底线是,只生成字符串的单元格
解析器过于专业化,不太有用。CSV文件更有用的Parsec框架是:
import Text.Parsec
import Text.Parsec.String
-- | `csv cell` parses a CSV file each of whose elements is parsed by `cell`
csv :: Parser a -> Parser [[a]]
csv cell = many (row cell)
-- | `row cell` parses a newline-terminated row of comma separated
-- `cell`-expressions
row :: Parser a -> Parser [a]
row cell = sepBy cell (char ',') <* char '\n'
在这里,不是使用一个单元格
子parser来显式地将逗号分隔的单元格解析为字符串,以提供给另一个解析器,“cell”是一个隐含的上下文,在这个上下文中调用一个提供的单元解析器来解析底层的输入流,在适当的点上,在输入流中间的一行中会有一个逗号分隔的单元格。我不确定垂直分析器的组成是什么意思。你介意扩大一点吗?关于你所要求的:一种采用解析器Foo[Bar]的方法
和解析器Bar Baz
并将其转换为解析器Foo Baz
。哦,我明白了。像这样简单的类型,目标比OP的问题要明确得多。谢谢你的澄清!我编写了一个支持垂直组合的解析器库https://github.com/quickdudley/phaser
customCell :: Parser Int
customCell = read <$> many1 digit
> parse (csv customCell) "" "1,2,3\n4,5,6\n"
Right [[1,2,3],[4,5,6]]
>