2010-03-18 56 views
3

parsec-3.1.0(http://hackage.haskell.org/package/parsec-3.1.0) 适用于任何标记类型。然而,像Text.Parsec.Char.satisfy这样的组合器只能为Char数据类型定义。似乎没有更多的普通对象可用。带自定义标记数据类型的parsec-3.1.0

我应该定义自己的版本还是错过了某些东西?

也许还有在Haskell不同的解析器库,允许:

  • 定制令牌类型
  • 定制解析器的状态(我需要解析状态格式 - 波前OBJ)

回答

4

广义的版本oneOf,noneOfanyChar可以构建出一个广义的satisfy,很容易:

oneOfT :: (Eq t, Show t, Stream s m t) => [t] -> ParsecT s u m t 
oneOfT ts = satisfyT (`elem` ts) 

noneOfT :: (Eq t, Show t, Stream s m t) => [t] -> ParsecT s u m t 
noneOfT ts = satisfyT (not . (`elem` ts)) 

anyT :: (Show t, Stream s m t) => ParsecT s u m t 
anyT = satisfyT (const True) 

satisfyT :: (Show t, Stream s m t) => (t -> Bool) -> ParsecT s u m t 
satisfyT p = tokenPrim showTok nextPos testTok 
    where 
     showTok t  = show t 
     testTok t  = if p t then Just t else Nothing 
     nextPos p t s = -- however you update position for your token stream 

可能看起来这些泛化似乎失踪,但你会发现,在这里这些概括做出t的类型可能不适合别人的令牌类型是真实的某些假设。假设它是ShowEq的一个实例,但我可以想象它们以其他方式显示的令牌类型,而不是show,并且可以通过==elem以外的某种方法实现一类令牌中的成员资格。

最后,一旦您的令牌类型不再是Char,您选择表示位置并进行更新的方式高度依赖于您对令牌和流的表示。

因此,我可以看到为什么更广义的形式不存在。

+0

你命名可以通过类型类来解决这些问题: >类令牌,其中 > showTok :: A - >字符串 > nextPosTok ::(适当的类型这里) > ... 到底你总是可以''newtype'你的令牌类型并提供你自己的定义。 – Tener 2010-03-19 16:55:39

+0

@Tener - 事实上,我就是这么做的 - 但Parsec 3没有在Stream类中放入nextPos函数,也没有定义Token类型类。 – MtnViewMark 2010-03-19 22:55:46