[英]How to parse integer with base prefix using parsec in haskell?
我正在尝试使用parsec解析haskell中的输入整数字符串。 字符串可以是十进制,八进制或十六进制。 对于十进制,八进制和十六进制, #o
由#d
, #o
或#x
的前缀指定,然后是整数。 如果没有指定前缀,则假定基数为10.这是我到目前为止所做的:
parseNumber = do x <- noPrefix <|> withPrefix
return x
where noPrefix = many1 digit
withPrefix = do char '#'
prefix <- oneOf "dox"
return $ case prefix of
'd' -> many1 digit
'o' -> fmap (show . fst . head . readOct) (many1 octDigit)
'x' -> fmap (show . fst . head . readHex) (many1 hexDigit)
但是,这不是编译,而是因类型错误而失败。 我不太了解类型错误,并且只想帮助解决这个问题。 任何可能的解决方法也将受到赞赏。
感谢您的时间和帮助。 :)
编辑: 这是我一直在犯的错误。
你有两个小错误:
一个缩进错误( return x
必须缩进与do
相比)并且withPrefix中的解析器不能return
,因为它们无论如何都将return
它们的结果。
parseNumber = do x <- noPrefix <|> withPrefix
return x
where noPrefix = many1 digit
withPrefix = do char '#'
prefix <- oneOf "dox"
case prefix of
'd' -> many1 digit
'o' -> fmap (show . fst . head . readOct) (many1 octDigit)
'x' -> fmap (show . fst . head . readHex) (many1 hexDigit)
这应该工作
在Megaparsec -Parsec的现代分支中,这个问题是不存在的(来自hexadecimal
文档 ):
以十六进制表示形式解析整数。 根据Haskell报告,预计十六进制数的表示除了此解析器不解析“0x”或“0X”前缀的事实。 程序员有责任在解析数字本身之前解析正确的前缀。
例如,您可以使其符合Haskell报告,如下所示:
hexadecimal = char '0' >> char' 'x' >> L.hexadecimal
所以在你的情况下你可以定义(注意它的可读性如何):
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
type Parser = Parsec Void String
parseNumber :: Parser Integer
parseNumber = choice
[ L.decimal
, (string "o#" *> L.octal) <?> "octal integer"
, (string "d#" *> L.decimal) <?> "decimal integer"
, (string "h#" *> L.hexadecimal) <?> "hexadecimal integer" ]
让我们尝试解析器(注意错误消息的质量):
λ> parseTest' (parseNumber <* eof) ""
1:1:
|
1 | <empty line>
| ^
unexpected end of input
expecting decimal integer, hexadecimal integer, integer, or octal integer
λ> parseTest' (parseNumber <* eof) "d#3"
3
λ> parseTest' (parseNumber <* eof) "h#ff"
255
λ> parseTest' (parseNumber <* eof) "o#8"
1:3:
|
1 | o#8
| ^
unexpected '8'
expecting octal integer
λ> parseTest' (parseNumber <* eof) "o#77"
63
λ> parseTest' (parseNumber <* eof) "190"
190
完全披露:我是Megaparsec的作者/维护者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.