2

Написал урезанный парсер S-выражений, вот код:

data Val = Int Integer
           | Float Double
           | String String
           | Symbol String
           | List [Val] deriving (Show)
-- blah blah blah
tList = do char '('
           list <- sepBy (tList <|> tAtom) (many $ char ' ')
           char ')'
           return $ List list
           <?> "list"

Вот такие выражения он парсит нормально:

(+ 2 (- 4 2))

Но если расставить табы, то он не работает:

(define (fac n)
    (if (= n 0)
        1
        (* n (fac (- n 1)))
    )
)

unexpected ")".

expecting " ", list or atomic expression

Как это пофиксить?

hamstertamer
  • 101
  • 1
  • 3
  • 14

1 Answers1

1

Очевидно потому что пробел не равен концу строки или табу:

list <- sepBy (tList <|> tAtom) (many $ char ' ')

У меня нет под рукой Haskell с Parsec, но наверное такое:

list <- sepBy (tList <|> tAtom) (many $ (char ' ' <|> char '\t' <|> char '\n'))

должно прокатить.

Vladimir Gordeev
  • 5,396
  • 1
  • 24
  • 41
  • Нет, все равно не работает (define f (+ 2 2) )

    (line 3, column 1): unexpected "}" expecting " ", "\t", "\n", block or atomic expression

    – hamstertamer Feb 27 '12 at 14:10
  • А не могли бы вы привести весь код? Это конечно увлекательно, вычислять ошибку, не видя текста, вслепую, но... – alexlz Feb 28 '12 at 03:49
  • http://pastebin.com/9ZHVtTAs – hamstertamer Feb 28 '12 at 13:24
  • sepBy захватывает пробелы перед ")". Используйте endBy. Кстати, там есть парсер space (который один из " \v\f\t\r\n" – alexlz Feb 28 '12 at 14:09
  • Используйте endBy

    Каким образом? Пример можно?

    – hamstertamer Feb 28 '12 at 14:29
  • Вместо sepBy
    tList = do 
       char '('
       block <- endBy (tList <|> tAtom) (many $ char ' ')
    
    – alexlz Feb 28 '12 at 14:42
  • И все равно не работает:

    unexpected ")" expecting " ", list or atomic expression

    – hamstertamer Feb 28 '12 at 14:50
  • Вот три здешних примера.
     (+ 2 (- 4 2))
     [List [Symbol "+",Int 2,List [Symbol "-",Int 4,Int 2]]]
     (define (fac n)
         (if (= n 0)
           1
            (* n (fac (- n 1)))
         )
     )
     [List [Symbol "define",List [Symbol "fac",Symbol "n"],Symbol "\n",List [Symbol "if",List [Symbol "=",Symbol "n",Int 0],Symbol "\n",Int 1,Symbol "\n",List [Symbol "*",Symbol "n",List [Symbol "fac",List [Symbol "-",Symbol "n",Int 1]]],Symbol "\n"],Symbol "\n"]]
    (define f
         (+ 2 2)
    )
     [List [Symbol "define",Symbol "f\n",List [Symbol "+",Int 2,Int 2],Symbol "\n"]]
    
    – alexlz Feb 28 '12 at 15:06
  • И мне нравится Symbol "\n" – alexlz Feb 28 '12 at 15:07