繁体   English   中英

如何使用haskell中的parsec解析带有基本前缀的整数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM