我为daily programmer redit challenge编写罗马数字解析器。我编写了一个parsec解析器来实现挑战的挑战部分。这是为了支持将其内容乘以1000的括号。
(II)II = 2002
现在我已经让解析器正常工作,但是使用try
并不是很清楚。
这有效:
romAdv :: GenParser Char st RomAdv
romAdv = complex <|> simple
但这不是:
romAdv :: GenParser Char st RomAdv
romAdv = try simple <|> complex
任何人都可以解释一下吗?我认为它们有点等同。
代码:
data Numeral = I | V | X | L | C | D | M deriving (Read, Show)
type RomNum = [Numeral] deriving (Read, Show)
data RomAdv = Bracketed RomAdv RomNum | Simple RomNum deriving (Read, Show)
romNumbers :: GenParser Char st [RomAdv]
romNumbers = do
numbers <- sepBy (romAdv) (char '\n')
eof
return numbers
romAdv :: GenParser Char st RomAdv
romAdv = complex <|> simple
complex :: GenParser Char st RomAdv
complex =
do multed <- between (char '(') (char ')') romAdv
remainder <- romNum
return (Bracketed multed remainder)
simple :: GenParser Char st RomAdv
simple = do
number <- romNum
return (Simple number)
romNum :: GenParser Char st [Numeral]
romNum = many numeral
numeral :: GenParser Char st Numeral
numeral = do
c <- char 'I' <|> char 'V' <|> char 'X' <|> char 'L' <|> char 'C' <|> char 'D' <|> char 'M'
return $ read [c]
答案 0 :(得分:3)
想出来。
因为这是我的语法会将""
解析为(Simple [])
。更改语法,以便Simple需要至少一个罗马数字,这给了我所需的行为。毕竟try
工作得很好,表现得像我想的那样,我只是不认识它。
data Numeral = I | V | X | L | C | D | M deriving (Read, Show)
type RomNum = [Numeral]
data RomAdv = Bracketed RomAdv RomNum | Simple Numeral RomNum deriving (Show)
romAdv :: GenParser Char st RomAdv
romAdv = try simple <|> complex
simple :: GenParser Char st RomAdv
simple = do
number1 <- numeral
number <- romNum
return (Simple number1 number)