Parsec:解析列表列表,两者都具有相同的分隔符
Parsec: Parsing a list of lists, both with the same delimiter
考虑一种简单的语言,它是 space 分隔命令的列表。每个命令都以一个字母作为命令名称,并以一系列 space 分隔的数字作为其参数;例如a 1 2 3 b 4 5 6 d 7 e f
将代表以下命令:
- a 1 2 3
- b 4 5 6
- d 7
- e
- f
问题是它一直在 sepBy
抓取物品,然后伸手去拿另一个号码,但当它到达 "b" 时失败了。
但是,当通过下面的代码传递时会产生以下错误:
Left "error" (line 1, column 5):
unexpected "b"
expecting space
我现在意识到这可能是因为我看待问题的方式有误,如果有人指出如何解析这样的问题,我将不胜感激。
module Main where
import Control.Applicative hiding (many, optional, (<|>))
import Text.ParserCombinators.Parsec
import Numeric (readSigned, readFloat)
commands = command `sepBy` spaces
command = do
l <- letter
ns <- number `sepBy` spaces
return (l, ns)
main :: IO ()
main = print $ show $ parse commands "error" "a 1 2 3 b 4 5 6 d 7 e f"
number :: CharParser () Double
number = do s <- getInput
case readSigned readFloat s of
[(n, s')] -> n <$ setInput s'
_ -> empty
尝试在每个非 space 令牌之后消耗 spaces。例如
commands = many (command <* spaces)
command = do
l <- letter
spaces
ns <- many (number <* spaces)
return (l, ns)
或
command = (,) <$> (letter <* spaces) <*> many (number <* spaces)
主要思想是:在你解析某些东西之后,下一个字符应该是非space开始下一个要解析的项目。
我会按照@chi 的建议编写解析器。
与 sepBy
的处理是,如果分隔符匹配,则 sepBy
期望解析另一个项目。
考虑一种简单的语言,它是 space 分隔命令的列表。每个命令都以一个字母作为命令名称,并以一系列 space 分隔的数字作为其参数;例如a 1 2 3 b 4 5 6 d 7 e f
将代表以下命令:
- a 1 2 3
- b 4 5 6
- d 7
- e
- f
问题是它一直在 sepBy
抓取物品,然后伸手去拿另一个号码,但当它到达 "b" 时失败了。
但是,当通过下面的代码传递时会产生以下错误:
Left "error" (line 1, column 5):
unexpected "b"
expecting space
我现在意识到这可能是因为我看待问题的方式有误,如果有人指出如何解析这样的问题,我将不胜感激。
module Main where
import Control.Applicative hiding (many, optional, (<|>))
import Text.ParserCombinators.Parsec
import Numeric (readSigned, readFloat)
commands = command `sepBy` spaces
command = do
l <- letter
ns <- number `sepBy` spaces
return (l, ns)
main :: IO ()
main = print $ show $ parse commands "error" "a 1 2 3 b 4 5 6 d 7 e f"
number :: CharParser () Double
number = do s <- getInput
case readSigned readFloat s of
[(n, s')] -> n <$ setInput s'
_ -> empty
尝试在每个非 space 令牌之后消耗 spaces。例如
commands = many (command <* spaces)
command = do
l <- letter
spaces
ns <- many (number <* spaces)
return (l, ns)
或
command = (,) <$> (letter <* spaces) <*> many (number <* spaces)
主要思想是:在你解析某些东西之后,下一个字符应该是非space开始下一个要解析的项目。
我会按照@chi 的建议编写解析器。
与 sepBy
的处理是,如果分隔符匹配,则 sepBy
期望解析另一个项目。