Haskell Parsec跳过所有未预定义的单词

Tae*_*lia 5 haskell parsec

学习使用Parsec库,作业的一部分.

编辑:欢迎使用其他库的建议,重点是解析.

我想要的是用大写字母提取所有单词,从任何句子中提取四个罗盘方向.例如:"比利时完全位于荷兰南部." 应找到并返回"比利时南荷兰".

我无法想象的是如何忽略(吃)任何不是指南针方向的输入.我正在寻找一些类似的东西

'many (not compassDirection >> space)'
Run Code Online (Sandbox Code Playgroud)

但g(h)oogle并没有帮助我.

以下代码显然停留在'many'函数上.

readExpr :: String -> String
readExpr input = case parse (parseLine) "" input of
    Left err -> "No match: " ++ show err
    Right val -> "Found: " ++ showVal val

parseLine :: Parser GraphValue
parseLine = do
            x <- parseCountry
            space
            many ( some (noneOf " ") >> space )
            y <- parseCompass
            space
            many ( some (noneOf " ") >> space )
            z <- parseCountry
            return $ Direction [x,y,z]

compassDirection :: Parser String
compassDirection = string "north" <|>
                   string "south" <|>
                   string "east" <|>
                   string "west"

parseCountry :: Parser GraphValue
parseCountry = do 
                c <- upper 
                x <- many (lower)
                return $ Country (c:x)

parseCompass :: Parser GraphValue
parseCompass = do 
                x <- compassDirection
                return $ Compass x
Run Code Online (Sandbox Code Playgroud)

Mat*_*ick 4

我不会详细说明,因为这是家庭作业,OP 说“重要的是解析”。


我解决这个问题的方法:

  • 对输入进行标记。将其分解为文字;这将使真正的解析步骤不必担心标记定义(即“%#@[ 是单词的一部分吗?”)或空格。这可以像这样简单,words或者您可以使用 Parsec 进行标记化。然后你就会拥有[Token](或者[String]如果你愿意的话)。

  • 罗盘方向的解析器。您已经有了这个(干得好),但是如果输入[String]不是String.

  • 以大写字母开头的单词的解析器。

  • 一个用于其他所有内容的解析器,只要它看到不是指南针方向或以大写字母开头的单词的标记,就会成功。

  • 可以处理任何标记的解析器,但可以使用代数数据类型来区分好东西和坏东西。

  • 可处理大量标记的解析器

希望这很清楚,但又不太清楚;例如,您仍然需要担心何时丢弃垃圾。基本思想是将问题分解为许多小子问题,解决子问题,然后将这些解决方案粘合在一起。