LINUX.ORG.RU

Parsec

 ,


0

2

Разбираюсь с парсеком, не могу понять в чем дело

Не мудрствуя лукаво вот мой парсер

https://github.com/s9gf4ult/projs/blob/master/fp/0912/doctorx.hs

Заранее предупреждаю: это с сентябрьского конкурса по ФП.

Никак не могу разобрать последовательность строк: сначала парсил только первое вхождение, сейчас уже ниче не парсит, почему то ожидает не то что я хочу.

Ответ на: комментарий от qnikst

Ну короче,

parseMan 

нормально работает с одной строкой, парсит строку такого вида

1: 'x', 2, -3, 4

И выдает Person.

Понимаю, что parsec для такой задачи - оверкилл, но хочу на парсеке, чтобы уметь.

parsePeople

должен парсить последовательность строк в файле и выдавать [Person]. Можно, конечно, тупо разбить вход с помощью lines, но это не parsec-way же.

s9gf4ult ★★
() автор топика
Ответ на: комментарий от theNamelessOne

Оно самое.

Мне надо парсер этого файла. Так как парсер - не часть решения, а просто вспомогательный код, который введет данные в программу, то выложил реквест тут.

s9gf4ult ★★
() автор топика
Ответ на: комментарий от s9gf4ult
module Main where

import Text.Parsec
import Text.Parsec.String
import Control.Applicative hiding ((<|>))

data Person = Person { num :: Int
                     , sym :: Char
                     , opinions :: [Opinion]
                     } deriving (Show)

data Opinion = Crazy Int
             | Normal Int
               deriving (Show)

parsePeople :: Parser [Person]
parsePeople = sepEndBy parsePerson newline <* eof

parsePerson :: Parser Person
parsePerson = Person <$> parseNum <*> parseChar <*> parseOpinions

parseNum :: Parser Int
parseNum = parseInt <* spaces <* char ':' <* spaces

parseChar :: Parser Char
parseChar = char '\'' *> spaces *> anyChar <* char '\''

parseInt :: Parser Int
parseInt = read <$> many1 digit

parseOpinions :: Parser [Opinion]
parseOpinions = char ',' *> spaces *> sepBy parseOpinion (char ',' *> spaces)

parseOpinion :: Parser Opinion
parseOpinion = Crazy <$> (char '-' *> parseInt)
           <|> Normal <$> parseInt

main :: IO ()
main = do input <- readFile "input.txt"
          case parse parsePeople "input.txt" input of
            Left err -> print err
            Right result -> mapM_ print result
> putStrLn =<< readFile "input.txt"
1: 'x', 2, -3, 4
2: 'y', -1, 3
3: 'z', -1, 2, -4
4: '@', -2, -3

> main
Person {num = 1, sym = 'x', opinions = [Normal 2,Crazy 3,Normal 4]}
Person {num = 2, sym = 'y', opinions = [Crazy 1,Normal 3]}
Person {num = 3, sym = 'z', opinions = [Crazy 1,Normal 2,Crazy 4]}
Person {num = 4, sym = '@', opinions = [Crazy 2,Crazy 3]}
> 

А ошибка у тебя вроде бы в том, что после символа пациента (строки 31-33 на гитхабе) должна парситься запятая, а у тебя ее нет.

theNamelessOne ★★★★★
()
Ответ на: комментарий от s9gf4ult

должен парсить последовательность строк в файле и выдавать [Person]

Вроде, many parseMan должно работать (с любой смесью разделителей - ' ', \n, \t).

quasimoto ★★★★
()
Ответ на: комментарий от theNamelessOne

после символа пациента (строки 31-33 на гитхабе) должна парситься запятая

Нет, не изза этого, запятая парсится в строке 36 (https://gist.github.com/3675577 на случай если поменяется git). Мой парсер для более общего случая, и разбирает строки даже если нет мнений.

*Main> parse parseMan "file" "22: 'f'"
Right (Person {persNmb = 22, persSymbol = 'f', persOpinions = []})
*Main> parse parseMan "file" "22: 'f', 44"
Right (Person {persNmb = 22, persSymbol = 'f', persOpinions = [OpNoraml 44]})
*Main> parse parseMan "file" "22: 'f', 44 , -2"
Right (Person {persNmb = 22, persSymbol = 'f', persOpinions = [OpNoraml 44,OpCrazy 2]})

Одну строку разбирает нормально, а вто когда несколько ... ладно парсер все равно у меня теперь есть.

s9gf4ult ★★
() автор топика
Ответ на: комментарий от s9gf4ult
> parse (many parseMan) "" "1: 'x', 2, -3, 4\n \t \n \n 2: 'y', -2, 3, -4\n3: 'z', 22, 31, 33"
Right [Person {persNmb = 1, persSymbol = 'x', persOpinions = [OpNoraml 2,OpCrazy 3,OpNoraml 4]},Person {persNmb = 2, persSymbol = 'y', persOpinions = [OpCrazy 2,OpNoraml 3,OpCrazy 4]},Person {persNmb = 3, persSymbol = 'z', persOpinions = [OpNoraml 22,OpNoraml 31,OpNoraml 33]}]

ещё минусы куда-то потерялись.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

spaces полгощает ентеры !!!!!!!!!!1111111111

Теперь я понял в чем косяк. Мой парсер ожидает что в конце каждой строки произвольное количество spaces

*Main> parse (many parseMan) "file" "22: 'f', 44 , -2 4: 'f' 34: 'q', 44, 44"
Right [Person {persNmb = 22, persSymbol = 'f', persOpinions = [OpNoraml 44,OpCrazy 2]},Person {persNmb = 4, persSymbol = 'f', persOpinions = []},Person {persNmb = 34, persSymbol = 'q', persOpinions = [OpNoraml 44,OpNoraml 44]}]
вот шиза .. а такой парсер даже еще более ощий и нестрогий.

s9gf4ult ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.