Haskell - 写一个小解析器

时间:2014-07-19 11:22:32

标签: parsing haskell

我想为足球比分写一点解析器。

例如,输入"0:2"应解析为Just (Score 0 2)。如果有类似"3:3"的内容,则应该给我"Nothing"。其他一切也应该给我"Nothing"

data Score = Score Int Int
deriving (Eq,Show,Ord)


runParsec :: Parser a -> String -> Maybe a
runParsec parser input = case runP parser () "" input of
Left  _ -> Nothing
Right a -> Just a

我将runParsec作为参数提供的解析器现在看起来像这样:

parseScore :: Parser Score
parseScore str1 = case str1 of
    "x:y" && (x /= y)   -> Right Score x y
    Otherwise           -> Left x

我知道,parseScore的这段代码无法正常工作。因为我无法模仿匹配像" x:y"这样的字符串。但是我该如何解决这个问题呢?

runParsec parseScore "0:2"应该给我Just (Score 0 2)

我很感谢提示。

谢谢!

1 个答案:

答案 0 :(得分:5)

只需为您的类型写一个合适的Parser并过滤掉您不需要的内容:

import Control.Applicative ((<$>))
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Char

data Score = Score Int Int deriving (Show)

parseScore :: Parser Score
parseScore = do
  a <- integer
  char ':'
  b <- integer
  return $ Score a b

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

runParsec :: String -> Maybe Score
runParsec input = case parse parseScore "" input of
  Left e -> Nothing
  Right e -> case e of
    Score 0 2 -> Just e
    _ -> Nothing

ghci演示:

λ> runParsec "0:2"
Just (Score 0 2)
λ> runParsec "3:3"
Nothing
λ> runParsec "3:4"
Nothing
  

如果我想接受所有分数,1:0,0:4等,我该怎么办?   一切,但没有随机输入,如&#34; jirjgir&#34;没有相同的分数   喜欢&#34; 2:2&#34;或&#34; 5:5&#34;

只需更改过滤条件:

runParsec :: String -> Maybe Score
runParsec input = case parse parseScore "" input of
  Left e -> Nothing
  Right e -> case e of
    Score x y -> if x == y
                 then Nothing
                 else Just e

演示:

λ> runParsec "1:0"
Just (Score 1 0)
λ> runParsec "0:4"
Just (Score 0 4)
λ> runParsec "2:2"
Nothing
λ> runParsec "jiraf"
Nothing