【问题标题】:Parser written in Haskell not working as intended用 Haskell 编写的解析器无法按预期工作
【发布时间】:2021-09-29 14:17:42
【问题描述】:

我在玩 Haskell 的 parsec 库。我试图将"#x[0-9A-Fa-f]*" 形式的十六进制字符串解析为整数。这是我认为可行的代码:

module Main where

import Control.Monad
import Numeric
import System.Environment
import Text.ParserCombinators.Parsec hiding (spaces)

parseHex :: Parser Integer
parseHex = do
  string "#x"
  x <- many1 hexDigit
  return (fst (head (readHex x)))

testHex :: String -> String
testHex input = case parse parseHex "lisp" input of
  Left err -> "Does not match " ++ show err
  Right val -> "Matched" ++ show val

main :: IO ()
main = do
  args <- getArgs
  putStrLn (testHex (head args))

然后我尝试在 Haskell 的 repl 中测试 testHex 函数:

GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( src/Main.hs, interpreted )
Ok, one module loaded.
*Main> testHex "#xcafebeef"
"Matched3405692655"
*Main> testHex "#xnothx"
"Does not match \"lisp\" (line 1, column 3):\nunexpected \"n\"\nexpecting hexadecimal digit"
*Main> testHex "#xcafexbeef"
"Matched51966"

第一次和第二次尝试按预期工作。但在第三个中,字符串匹配到无效字符。我不希望解析器执行此操作,但如果字符串中的任何数字不是有效字符串,则不匹配。为什么会发生这种情况,如果解决这个问题怎么办?

谢谢!

【问题讨论】:

  • 通常像这样的解析器会被嵌入到一个更大的解析器中,就像一个会期望在十六进制数之后有一些加号或括号或分号或其他东西的解析器。在这种情况下,您确实希望十六进制数字解析器成功并在第一个无效字符处停止 - 让包含在其中的解析器的其余部分继续执行。
  • @DanielWagner 这实际上很有意义。谢谢!

标签: parsing haskell parsec


【解决方案1】:

你需要把eof放在最后。

parseHex :: Parser Integer
parseHex = do
  string "#x"
  x <- many1 hexDigit
  eof
  return (fst (head (readHex x)))

或者,如果您想在其他地方重用parseHex,您可以使用eof 组合它。

testHex :: String -> String
testHex input = case parse (parseHex <* eof) "lisp" input of
  Left err -> "Does not match " ++ show err
  Right val -> "Matched" ++ show val

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    相关资源
    最近更新 更多