Haskell attoparsec не распознает новую строку при разборе из текстового файла - PullRequest
0 голосов
/ 08 мая 2018

Я пытался разобрать файл .txt с некоторым английским текстом в нем. Мой код пытается вернуть количество абзацев в этом файле .txt. По какой-то причине attoparsec не может распознать символ новой строки или любые другие символы, такие как \n\r\t. Ниже мой код. Я также пытался использовать many1 (satisfy (inClass "\n\r\t")), но все равно не повезло. Как вы думаете, в чем основная проблема? Также вот ссылка на образец текстового файла Я проверял его на.

import Data.Attoparsec.Text
import qualified Data.Text as T
import qualified Data.Text.IO as Txt

newtype Prose = Prose {
  word :: [Char]
}

instance Show Prose where
  show a = word a

optional :: Parser a -> Parser ()
optional p = option () (try p *> pure ())

specialChars = ['-', '_', '…', '“', '”', '\"', '\'', '’', '@', '#', '$',
                '%', '^', '&', '*', '(', ')', '+', '=', '~', '`', '{', '}',
                '[', ']', '/', ':', ';', ',']

inputPara :: Parser Prose
inputPara = Prose <$> many1' (letter <|> digit <|> space <|> satisfy (inClass specialChars) <|> satisfy (inClass "――.?!") )

paraSeparator :: Parser ()
paraSeparator = many1 (satisfy (isEndOfLine) <|> satisfy (isHorizontalSpace)) >> pure ()

paraParser :: String -> [Prose]
paraParser str = case parseOnly wp (T.pack str) of
    Left err -> error err
    Right x -> x
    where
      wp = optional paraSeparator *> inputPara `sepBy1` paraSeparator

main :: IO()
main = do
  input <- readFile "test.txt"
  let para = paraParser input
  print para
  print $ length para

1 Ответ

0 голосов
/ 08 мая 2018

Проблема в том, что space анализатор в следующей строке:

inputPara = Prose <$> many1' (letter <|> digit <|> space <|> satisfy (inClass specialChars) <|> satisfy (inClass "――.?!") )

соответствует символам, таким как \n\r\t (каждый символ, который isSpace)

Именно поэтому inputPara соответствует всему тексту без разделения.

Одним из решений может быть удаление парсера space из inputPara и добавление символа ' ' в specialChars

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

import Data.Attoparsec.Text
import qualified Data.Text as T
import qualified Data.Text.IO as Txt
import Control.Applicative ((<|>))

newtype Prose = Prose {
  word :: [Char]
}

instance Show Prose where
  show a = word a

optional :: Parser a -> Parser ()
optional p = option () (try p *> pure ())

specialChars = ['-', '_', '…', '“', '”', '\"', '\'', '’', '@', '#', '$',
                '%', '^', '&', '*', '(', ')', '+', '=', '~', '`', '{', '}',
                '[', ']', '/', ':', ';', ',', ' ']

inputPara :: Parser Prose
inputPara = Prose <$> many1' (letter <|> digit <|> satisfy (inClass specialChars) <|> satisfy (inClass "――.?!") )

paraSeparator :: Parser [Char]
paraSeparator = many1 space

paraParser :: String -> [Prose]
paraParser str = case parseOnly wp (T.pack str) of
    Left err -> error err
    Right x -> x
    where
      wp = optional paraSeparator *> inputPara `sepBy1` paraSeparator

main :: IO()
main = do
  input <- readFile "test.txt"
  let para = paraParser input
  print para
  print $ length para
...