如何在Haskell代码中实现浮点解析器功能以进行整数处理?

问题描述 投票:0回答:1

参考我的作业说明(我是只有Haskell的基础经验的学生),我必须使用Text.Parsec制作一个简单的计算器解析器。到目前为止,该程序可以读取一些字符串输入以仅通过整数值执行解析,例如:

parseTest addition "5 + 8 / 4"

我实际上有该程序的完整代码:

import Text.Parsec hiding(digit)
import Data.Functor

type CalcParser a = Parsec String () a

digit :: CalcParser Char
digit = oneOf ['0'..'9']

number :: CalcParser Integer
number = read <$> many1 digit

fp_char :: CalcParser String 
fp_char = many1 digit


applyMany :: a -> [a -> a] -> a
applyMany x [] = x
applyMany x (h:t) = applyMany (h x) t


div_ :: CalcParser (Integer -> Integer -> Integer)
div_= do
    char '/'
    return div

star :: CalcParser (Integer -> Integer -> Integer)
star = do
    char '*'    
    return (*)  

plus :: CalcParser (Integer -> Integer -> Integer)
plus = do
    char '+'    
    return (+)

minus :: CalcParser (Integer -> Integer -> Integer)
minus = do
    char '-'    
    return (-)  

multiply :: CalcParser Integer
multiply = do
    spaces
    lhv <- enclosed
    spaces
    t <- many tail
    return $ applyMany lhv t
    where tail =
                do
                    f <- star <|> div_
                    spaces
                    rhv <- enclosed
                    spaces
                    return (`f` rhv)


add :: CalcParser Integer
add = do
    spaces
    lhv <- multiply <|> fact' <|> negation'
    spaces
    t <- many tail
    return $ applyMany lhv t
    where tail =
                do
                    f <- plus <|> minus
                    spaces
                    rhv <- multiply <|> fact' <|> negation'
                    spaces
                    return (`f` rhv)

enclosed :: CalcParser Integer
enclosed = number <|> do
    char '('
    res <- add
    char ')'
    return res

-- factorial    
fact' :: CalcParser Integer
fact' = do
    spaces
    char '!'
    rhv <- number
    return $ factorial rhv  

factorial :: Integer -> Integer
factorial n
    | n < 0 = error "No factorial exists for negative inputs" 
    | n == 0 || n == 1 = 1
    | otherwise = acc n 1
    where
    acc 0 a = a
    acc b a = acc (b-1) (b * a)  

-- negation 
negation' :: CalcParser Integer
negation' = do
    spaces
    char '~'
    rhv <- enclosed
    spaces
    return $ negate rhv

上面的清单包括用于主要运算的函数定义,这些函数的定义带有否定和阶乘计算选项。我需要的只是使该程序对浮点值以及任何字符串输入中的整数敏感。我如何通过调用唯一的函数(适用于小数和整数)来实现该功能以启动解析器,如下所示(例如):

parseTest totalCalc "~(8.44 * 12.85 / 3.2) * !4"

我输入'!'阶乘符号的数字部分之前的字符,因为解析器似乎无法识别正常的“ 4!”或类似的字符序列作为阶乘指示符。

parsing haskell parsec parser-combinators
1个回答
0
投票

步骤1:搜索+将所有出现的Integer替换为Double。现在,您的解析器仍然只能读取整数,但在内部将其表示为Double

步骤2:使number解析器解析整数或浮点数。您已经记下的整数:只是一个数字序列。让我们重命名它以更好地反映它在做什么:

parseInt :: CalcParser Double
parseInt = read <$> many1 digit

浮点数并不难得多:它是一个数字序列,后跟一个点(句点),然后是另一个数字序列:

parseDouble :: CalcParser Double
parseDouble = do
    whole <- many1 digit
    char '.'
    fract <- many1 digit
    pure $ read $ whole <> "." <> fract

然后any数字将只是“ double或int”:

number :: CalcParser Double
number = try parseDouble <|> parseInt
© www.soinside.com 2019 - 2024. All rights reserved.