Parsing 深入扩展解析器库的方法

Parsing 深入扩展解析器库的方法,parsing,haskell,functional-programming,parser-combinators,Parsing,Haskell,Functional Programming,Parser Combinators,我找到的关于解析器组合器的材料涵盖了通过组合来构建复杂的解析器,但是我想知道是否有好的方法可以通过调整库的组合解析器而不完全复制原始库的逻辑来定义解析器 例如,下面是在中定义的简化CSV解析器 假设一个库中定义了csvFile,那么另一个库是否可以使用自定义版本的cell解析器创建自己的CSV解析器,而不必重写行和csvFile解析器?是否可以重写源库以实现这一点?这对于CSV解析器来说足够简单,但我对一个广泛适用的解决方案感兴趣 通常,您需要对要替换的组件的签名进行抽象。例如,在CSV示例中,

我找到的关于解析器组合器的材料涵盖了通过组合来构建复杂的解析器,但是我想知道是否有好的方法可以通过调整库的组合解析器而不完全复制原始库的逻辑来定义解析器

例如,下面是在中定义的简化CSV解析器


假设一个库中定义了
csvFile
,那么另一个库是否可以使用自定义版本的
cell
解析器创建自己的CSV解析器,而不必重写
csvFile
解析器?是否可以重写源库以实现这一点?这对于CSV解析器来说足够简单,但我对一个广泛适用的解决方案感兴趣

通常,您需要对要替换的组件的签名进行抽象。例如,在CSV示例中,我们需要扩展
csvFile
的类型,以允许我们在自定义
单元格中插入插槽

line cell = sepBy cell (char ',')
csvFile cell = endBy (line cell) eol
显然,这很快就会变得笨拙。但是,我们可以将所有需要的扩展点打包到一个字典中,并将其传递给其他人

data LanguageDefinition =
  LanguageDefinition { cell :: Parser Cell 
                     , ...
                     }
然后,我们通过这个
语言定义

data Parsers = Parsers { line :: Parser Line, csvFile :: Parser [Line], ... }

mkParsers :: LanguageDefinition -> Parsers
这正是Parsec的广义令牌解析模块所采用的方法:请参阅和


甚至可以采取更为通用的方法,将越来越多的东西抽象到正在流传的词典中。实际上,这是一种面向对象或OCaml模块的代码组织方法,非常有效

民间表达问题表明,在引入更多功能和引入更多变体之间存在着紧张关系。在这种情况下,您需要一个新的变体,因此需要修复该功能(并在字典中列出所有内容)。这将为引入新变体开辟道路

data Parsers = Parsers { line :: Parser Line, csvFile :: Parser [Line], ... }

mkParsers :: LanguageDefinition -> Parsers