Parsing 三元组的Haskell解析器

Parsing 三元组的Haskell解析器,parsing,haskell,functional-programming,Parsing,Haskell,Functional Programming,我目前正在做一项关于Haskell解析的作业,但我正在努力学习一些基础知识 作业: 我应该创建一个函数,将字符串解析为三元组列表。 以便: A、 B,C ,E,D 会导致 Triples [("A","B","C"), ("A","E","D")] 输入字符串将包括:\作为一个新三元组开始的标志。字符串将以一个点结束。 三元组的元素可以是字母、数字或组合, e、 g.abc,a,1,abc121 所以, "a,b,c;\n d,e;\n f,g;\n h,i." 将导致: Triples

我目前正在做一项关于Haskell解析的作业,但我正在努力学习一些基础知识

作业: 我应该创建一个函数,将字符串解析为三元组列表。 以便: A、 B,C ,E,D

会导致

Triples [("A","B","C"), ("A","E","D")]
输入字符串将包括:\作为一个新三元组开始的标志。字符串将以一个点结束。 三元组的元素可以是字母、数字或组合, e、 g.abc,a,1,abc121

所以,

"a,b,c;\n d,e;\n f,g;\n h,i."  
将导致:

Triples [("a","b","c"),("a","d","e"),("a","f","g"),("a","h","i")]
我当前的解决方案: 这个函数非常简单和正确。获取字符串并返回一个newtype Triples对象,其中包含由parseTriples创建的Triples列表

parseTriples :: Parser [Triple]
parseTriples = parseTriple 
            >>= \r -> ((string ";\n" >> parseTriples >>= \rs -> return (r:rs)) 
            P.<|>(return[r]))
导入:

newtype Triples = Triples [Triple] deriving (Show,Eq)
type Triple = (String, String, String) 
import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?=))
import qualified Text.Parsec as P (char,runP,noneOf,many,(<|>),eof)
import Text.ParserCombinators.Parsec
import Text.Parsec.String 
import Text.Parsec.Char
import Data.Maybe
导入Test.HUnit(runTestTT,Test(TestLabel,TestList),(~?=) 将限定的Text.Parsec作为P导入(char、runP、noneOf、many、()、eof) 导入Text.ParserCombinators.Parsec 导入Text.Parsec.String 导入Text.Parsec.Char 导入数据,也许吧 测试用例

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

-- | Tests the implementations of 'parseScore'.
main :: IO ()
main = do
    testresults <- runTestTT tests
    print testresults

-- | List of tests for 'parseScore'.
tests :: Test
tests = TestLabel "parseScoreTest" (TestList [
    runParsec parseTriplesD "0,1,2;\n2,3."   ~?= Just (Triples [("0","1","2"),("0","2","3")]),
    runParsec parseTriplesD "a,bcde ,23." ~?= Just (Triples [("a","bcde ","23")]),
    runParsec parseTriplesD "a,b,c;\n d,e;\n f,g;\n h,i." ~?= Just (Triples [("a","b","c"),("a","d","e"),("a","f","g"),("a","h","i")]),
    runParsec parseTriplesD "a,bcde23." ~?= Nothing,
    runParsec parseTriplesD "a,b,c;d,e;f,g;h,i." ~?= Nothing,
    runParsec parseTriplesD "a,b,c;\nd;\nf,g;\nh,i." ~?= Nothing
    ])
runParsec::Parser a->String->Maybe a
runParsec parser input=case P.runP parser()“”的输入
左->无
对->只是一个
--|测试“parseScore”的实现。
main::IO()
main=do
testresults您可以做的是:

  • 解析第一个字符
  • 解析成对的列表
  • 将第一个字符添加到每个对以创建三元组
  • 使用
    do
    符号将使代码更具可读性。
    您可以使用
    alphaNum
    作为
    字母数字的缩写

    parseTriplesD :: Parser Triples
    parseTriplesD = Triples <$> parseTriples
    
    parseTriples :: Parser [Triple]
    parseTriples = do
        a <- parseString
        char ','
        pairs <- parsePair `sepBy1` string ";\n"
        char '.'
        eof
        return (map (\(b, c) -> (a, b, c)) pairs)
    
    parsePair :: Parser (String, String)
    parsePair = do
        first <- parseString
        char ','
        second <- parseString
        return (first, second)
    
    parseString :: Parser String
    parseString = many (char ' ') >> many (alphaNum <|> char ' ')
    
    parsetriples::解析器三元组
    parseTriples=Triples parseTriples
    parseTriples::解析器[Triple]
    parseTriples=do
    
    a您的第二个测试显示在
    “bcde”
    上的预期输出中捕获的空间。我以为输出中只需要字母数字字符。那是打字错误吗?啊。错过了那个。我们没有得到直接的任务指示,只有测试用例。所以我假设它只是字母数字字符,但我完全忽略了那个空格字符。我将在我的问题中编辑它。好主意。我没想到。你能再解释一下pairs>可选(字符“”)吗?“sepBy 1”和可选选项有什么作用?以下是和的文档
    sepBy1
    将解析由第二个参数分隔的第一个参数的列表
    optional
    将尝试解析某些内容,但如果匹配失败,则会忽略它。
    runParsec :: Parser a -> String -> Maybe a
    runParsec parser input = case P.runP parser () "" input of
        Left  _ -> Nothing
        Right a -> Just a
    
    -- | Tests the implementations of 'parseScore'.
    main :: IO ()
    main = do
        testresults <- runTestTT tests
        print testresults
    
    -- | List of tests for 'parseScore'.
    tests :: Test
    tests = TestLabel "parseScoreTest" (TestList [
        runParsec parseTriplesD "0,1,2;\n2,3."   ~?= Just (Triples [("0","1","2"),("0","2","3")]),
        runParsec parseTriplesD "a,bcde ,23." ~?= Just (Triples [("a","bcde ","23")]),
        runParsec parseTriplesD "a,b,c;\n d,e;\n f,g;\n h,i." ~?= Just (Triples [("a","b","c"),("a","d","e"),("a","f","g"),("a","h","i")]),
        runParsec parseTriplesD "a,bcde23." ~?= Nothing,
        runParsec parseTriplesD "a,b,c;d,e;f,g;h,i." ~?= Nothing,
        runParsec parseTriplesD "a,b,c;\nd;\nf,g;\nh,i." ~?= Nothing
        ])
    
    parseTriplesD :: Parser Triples
    parseTriplesD = Triples <$> parseTriples
    
    parseTriples :: Parser [Triple]
    parseTriples = do
        a <- parseString
        char ','
        pairs <- parsePair `sepBy1` string ";\n"
        char '.'
        eof
        return (map (\(b, c) -> (a, b, c)) pairs)
    
    parsePair :: Parser (String, String)
    parsePair = do
        first <- parseString
        char ','
        second <- parseString
        return (first, second)
    
    parseString :: Parser String
    parseString = many (char ' ') >> many (alphaNum <|> char ' ')