2010-03-18 5 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, что позволяет:

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

ответ

4

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

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

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

+0

вопросы вы назвали может быть решена: класса типов > класс фишку где > showTok :: а -> Строка > nextPosTok :: (соответствующий тип здесь) > ... В конце концов вы всегда можете «newtype» использовать свой токен и предоставлять свои собственные определения. – Tener

+0

@Tener - Действительно, так я бы это сделал, но Parsec 3 не помещал функцию nextPos в класс типа Stream, а также не определял тип маркера Token. – MtnViewMark

Смежные вопросы