#haskell #parsec
#haskell #парсек
Вопрос:
Я использую Parsec для анализа файла, который выглядит следующим образом:
## public_id
ANALOG-CLOCK
## name
Analog Wall Clock
Some more text...
## domain
Time measurement
More text here...
за исключением того, что файл может иметь переменное количество разделов, где каждый раздел начинается со строки «# #» и может содержать 0 строк содержимого.
type Model = [Section]
data Section = Section String [String]
deriving Show
headingLine :: Parser String
headingLine = do
try (string "##")
spaces
title <- many1 (noneOf "rn")
char 'n'
return title
nonHeadingLine :: Parser String
nonHeadingLine = do
try (noneOf "#")
contents <- many1 (noneOf "rn")
char 'n'
return contents
section :: Parser Section
section = do
title <- headingLine
contentLines <- many1 nonHeadingLine
spaces
return $ Section title contentLines
model :: Parser Model
model = do
s1 <- section
s2 <- section
s3 <- section
return [s1, s2, s3]
--return $ many1 section
main :: IO ()
main = do
modelStr <- readFile "analog3.md"
let result = do parse model "" modelStr
case result of
Left err -> putStrLn $ "Error " show err
Right mdl -> putStrLn $ show mdl
Я хочу, чтобы результат выглядел примерно так:
[Section "public_id" "ANALOG-CLOCK",Section "name" "Analog Wall Clock",Section "domain" "Time measurement"]
Код работает, когда у меня есть ровно одна строка содержимого на раздел, и выдает вышеуказанный результат.
У меня две проблемы:
1) Код не работает, когда у меня более одной строки содержимого на раздел, и
2) Когда я использую return $ many1 section
вместо return [s1, s2, s3]
, я получаю сообщение об ошибке типа «Не удалось сопоставить данные типа ‘Text.Parsec.Prim.ParsecT String ().Функтор.Идентификация.Идентификация [Section]’с ‘[Section]’ «.
Как мне заставить его обрабатывать более одной строки содержимого и как мне заставить его обрабатывать более одного раздела? Спасибо.
Комментарии:
1.
many1
это уже монадический тип, поэтому вам не нужно использоватьreturn
его. Просто введитеmany1 section
. «return» не является ключевым словом в Haskell; это функция, которая встраивает значение в монаду:return :: Monad m => a -> m a
2. Спасибо! Это избавляет от ошибки типа, но я получаю ошибку времени выполнения «Ошибка (строка 12, столбец 1): неожиданный конец ввода, ожидающий пробел или «##» «. У меня такое чувство, что я неправильно разделяю / завершаю разделы, но я не знаю, как мне следует.
3. @citrus Похоже, что он запускается
headingLine
в конце файла, после того, как все это уже было проанализировано. Если у вас теперь естьmany1 section
в конце вашейmodel
функции, но вы забыли удалить предыдущие четыре строки, это приведет к тому, что она попытается проанализировать по крайней мере четыре раздела, когда их всего три.4. @DarthFennec: Спасибо, это сработало! Я забыл удалить другие строки.