星期一早上的 Haskell 帖子Parsing Part 2: Applicative Parsing说这个关于交替的regex-applicative
:
请注意,顺序很重要!如果我们把整数解析器放在第一位,我们就有麻烦了!如果遇到小数,整数解析器会贪婪地成功解析小数点之前的所有内容。我们将丢失小数点后的所有信息,或者更糟糕的是,解析失败。
从他们的 Git 存储库中引用这个函数:
numberParser :: RE Char Value
numberParser = (ValueNumber . read) <$>
(negativeParser <|> decimalParser <|> integerParser)
where
integerParser = some (psym isNumber)
decimalParser = combineDecimal <$> many (psym isNumber) <*> sym '.' <*> some (psym isNumber)
negativeParser = (:) <$> sym '-' <*> (decimalParser <|> integerParser)
combineDecimal :: String -> Char -> String -> String
combineDecimal base point decimal = base ++ (point : decimal)
但是,我无法弄清楚为什么会这样。当我更改decimalParser <|> integerParser
为 时integerParser <|> decimalParser
,它似乎仍然总是解析正确的东西(特别是,我这样做并运行stack test
时,他们的测试仍然通过)。小数解析器必须有小数点,而整数解析器不能有小数点,所以它会在那里停止解析,导致小数点导致下一段解析失败,将我们回溯到小数解析器。似乎唯一不会发生这种情况的情况是,如果整个解析器的下一部分在此之后可以接受小数点(使其成为模棱两可的语法),但您仍然不会“丢失所有信息之后小数点,或更糟糕的是,解析失败”。我的推理是否正确并且那篇文章中有一个错误,或者是否有一个案例我没有看到他们的结果之一可能发生在哪里?