Attoparsec - убедитесь, что все содержимое используется sepBy1 - PullRequest
2 голосов
/ 20 мая 2019

Я бы хотел, чтобы приведенный ниже код возвращал [LoadInt 1,LoadDub 2.5,LoadInt 3], но он не работает после анализа [LoadInt 1,LoadDub 2] и обращения к .5,3.Как мне сделать так, чтобы он анализировался полностью до запятой, чтобы синтаксический анализ был успешным, и int синтаксический анализ на 2.5 является неудачным?

import qualified Data.Attoparsec.ByteString.Char8 as A
import Data.Attoparsec.ByteString.Char8 (Parser)
import Data.ByteString.Char8 (pack)
import Data.Attoparsec.Combinator
import Control.Applicative ((*>),(<$>),(<|>))
data LoadNum = LoadInt Int | LoadDub Double deriving (Show)

someFunc :: IO ()
someFunc = putStrLn . show $ A.parseOnly (lnParser <* A.endOfInput) (pack testString)


testString :: String
testString = "1,2.5,3"

lnParser :: Parser [LoadNum]
lnParser = (sepBy1' (ld <* A.atEnd) (A.char ','))

double :: Parser Double
double = A.double

int :: Parser Int
int = A.signed A.decimal

ld :: Parser LoadNum
ld = ((LoadInt <$> int ) <|> (LoadDub <$> double))

1 Ответ

2 голосов
/ 20 мая 2019

Вы можете использовать небольшую оглядку, чтобы решить, достигли ли вы конца элемента списка.Итак:

int :: Parser Int
int = do
    i <- A.signed A.decimal
    next <- A.peekChar
    case next of
        Nothing -> pure i
        Just ',' -> pure i
        _ -> fail "nah"
...