parsec-3.1.0 с пользовательским типом токена - PullRequest
3 голосов
/ 19 марта 2010

парсек-3.1.0 (http://hackage.haskell.org/package/parsec-3.1.0) работает с любым типом токена. Однако есть такие комбинаторы, как Text.Parsec.Char.satisfy, которые определены только для типа данных Char. Кажется, нет более общего аналога.

Должен ли я определить свои собственные версии или я что-то упустил?

Возможно, в Haskell есть разные библиотеки парсеров, которые позволяют:

  • пользовательские типы токенов
  • пользовательский анализатор состояния (мне нужно проанализировать формат с сохранением состояния - Wavefront OBJ)

1 Ответ

4 голосов
/ 19 марта 2010

Обобщенные версии oneOf, noneOf и anyChar могут быть построены из обобщенного 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, которые могут быть неверными для чьего-либо типа токена. Предполагается, что это экземпляр Show и Eq, но я могу представить типы токенов, для которых они отображаются не так, как show, и что членство в классе токенов может быть достигнуто с помощью другого чем == и elem.

Наконец, когда тип вашего токена больше не является Char, то, как вы решите представлять позицию и, соответственно, обновлять ее, сильно зависит от вашего представления токенов и потоков.

Следовательно, я понимаю, почему не существует более обобщенной формы.

...