Parsing 如何使用Haskell Parsec阻止不一致的浮点输入?
我被指派使用Haskell解析器组合器(即,通过导入Parsec.Text)制作一个相当简单的计算器解析器。该解析器需要对整数和浮点输入进行操作。有一个基本的代码来介绍我正在寻找的东西:Parsing 如何使用Haskell Parsec阻止不一致的浮点输入?,parsing,haskell,parsec,Parsing,Haskell,Parsec,我被指派使用Haskell解析器组合器(即,通过导入Parsec.Text)制作一个相当简单的计算器解析器。该解析器需要对整数和浮点输入进行操作。有一个基本的代码来介绍我正在寻找的东西: import Text.Parsec hiding(digit) import Data.Functor type Parser a = Parsec String () a digit :: Parser Char digit = oneOf ['0'..'9'] number :: Parser In
import Text.Parsec hiding(digit)
import Data.Functor
type Parser a = Parsec String () a
digit :: Parser Char
digit = oneOf ['0'..'9']
number :: Parser Integer
number = read <$> many1 digit
fp_char :: Parser String
fp_char = many1 digit
fp_number :: Parser Double
fp_number = read <$> parser where
parser = (++) <$> fp_char <*> (option "" $ (:) <$> char '.' <*> fp_char)
addition :: Parser Integer
addition = do
lhv <- number
spaces
char '+'
spaces
rhv <- number
return $ lhv + rhv
fp_addition :: Parser Double
addition = do
lhv <- fp_number
spaces
char '+'
spaces
rhv <- fp_number
return $ lhv + rhv
两者都被认为是错误触发器,但在上面的代码中,它被证明接受了一部分错误输入:事实上,一旦出现错误字符(如字母),解析器就会丢弃它,后面的字符也会被删除。因此,当相同或相似的输入仍然是有效的输入数据时,问题就出现了,即使它部分消失了。我的解决方案与此功能有关:
isValidInput :: Parser String -> Bool
isValidInput (x:xs) = if x `elem` ['0'..'9'] then isValidInput xs else False
由于
isValidInput
导致类型不正确,因此无法工作。更重要的是,我不理解如何使用这个辅助代码将其添加到核心计算函数中,比如这里给出的fp_加法 作为一般规则,Parsec解析器应该写入以使用输入流的有效前缀,并在不识别的第一个字符处停止
因此,字符串“123h.578”
应该由fp\u number
或number
成功解析,因为前缀“123”
对于这些解析器来说是可接受的输入。因此,您现有的解析器fp_number
和number
具有正确的行为:
> parseTest fp_number "123h.578"
123.0 -- this is correct
> parseTest number "123h.578"
123 -- this is also correct
应在更高级别上检查此无效h
字符。通常,您将拥有一个顶级解析器,该解析器尝试解析整个流,并使用eof
解析器来确保不存在不可解析的字符。例如,解析器:
fp_expression :: Parser Double
fp_expression =
(try fp_addition <|> fp_number) <* eof
在拒绝其他示例的同时:
> parseTest fp_expression "123h.578"
parse error at (line 1, column 4):
unexpected 'h'
expecting "." or end of input
> parseTest fp_expression "600.w57"
parse error at (line 1, column 5):
unexpected "w"
您不需要显式的isValidInput
函数。如果要定义一个表达式,可能需要通过运行类似于fp_expression
的解析器来实现,以查看它是否能够成功解析整个流
此外,你可能会发现学习有帮助。通读“非常简单的表达式解析”一章将帮助您学习编写这种解析器的基础知识 非常有力的回答,谢谢。我会用你们推荐的教程来提高我的理解力。
> parseTest fp_expression "123+0.578"
123.578
> parseTest fp_expression "123.578"
123.578
> parseTest fp_expression "123h.578"
parse error at (line 1, column 4):
unexpected 'h'
expecting "." or end of input
> parseTest fp_expression "600.w57"
parse error at (line 1, column 5):
unexpected "w"