如何检查解析是否失败?

时间:2014-10-05 12:18:59

标签: string parsing haskell

我想继续将解析器应用于字符串,并添加其输出,直到我到达字符串的末尾。不幸的是,当我解析字符串的结尾时,它失败了所以我得到一个空列表。我希望能够检查解析是否失败,然后在失败的解析之前获取所有解析的输出。我试图将此字符串解析为浮点列表。如何阻止这种情况发生(即获取一个空列表而不是我的浮动列表)。

我编写了一个这种类型的解析器:newtype Parser a = MkP (String -> [(String,a)]) 它的monad实例是这样的:

-- (>>=) :: m a -> (a -> m b) -> m b
instance Monad Parser where 
    return x = MkP f
        where
            f inp = [(inp,x)]
    f >>= g = MkP s 
        where
            s inp = [(rest,out) | (firstremain,firstout) <- applyParser f inp, (rest,out) <- applyParser (g firstout) firstremain]

失败的解析由空列表[]表示。我有这些主要的解析器:

item :: Parser Char
item = MkP f
    where
        f [] = []
        f (x:xs) = [(xs,x)]


zero :: Parser Char
zero = MkP f
    where
        f _ = []

我正在尝试解析此字符串:

unparsedboeyield = "0.63    0.81    1.01    1.20    1.38    1.54    1.68    1.79    1.89    1.97    2.05    2.11    2.17    2.23    2.28    2.33    2.37    2.42    2.45    2.49    2.53    2.56    2.59    2.62    2.64    2.67    2.69    2.71    2.73    2.75    2.77    2.79    2.80    2.82    2.83    2.84    2.85    2.87    2.87    2.88    2.89    2.90    2.90    2.91    2.91    2.92    2.92    2.92    2.93    2.93"

使用此解析器:

numberParser :: Parser Float
numberParser = do
    a <- item
    b <- item
    c <- item
    d <- item
    let number = read [a,b,c,d] :: Float in return number

yieldParser :: Parser [Float]
yieldParser = do
    x <- numberParser
    helper [x] where
        helper y = do 
            a <- randomthing
            helper (y ++ [a])
        randomthing = do
            item
            item
            item
            item
            numberParser

我不明白在helper时发生了什么,什么是a当randomthing失败时(它不能是[]那么它会引发类型错误,因为它不是浮动)。当我尝试解析字符串时会发生这种情况:

applyParser yieldParser boeunparsedyield =&gt; []

整个代码在这里:

import Control.Monad
import Data.Char


interpolate :: (Ord a, Fractional a) => ((a,a),(a,a)) -> a -> a
interpolate ((x1,y1),(x2,y2)) x = if (x > x2) || (x < x1) then error "value out of range" else y1 + difference * gradient

    where
        gradient = (y1 -y2)/(x1 - x2)
        difference = x - x1


pvt :: Fractional a => a -> Int -> a
pvt x t = x / (m + spotrate t)^t where m = 1 :: Fractional a => a

unparsedboeyield :: String
unparsedboeyield = "0.63    0.81    1.01    1.20    1.38    1.54    1.68    1.79    1.89    1.97    2.05    2.11    2.17    2.23    2.28    2.33    2.37    2.42    2.45    2.49    2.53    2.56    2.59    2.62    2.64    2.67    2.69    2.71    2.73    2.75    2.77    2.79    2.80    2.82    2.83    2.84    2.85    2.87    2.87    2.88    2.89    2.90    2.90    2.91    2.91    2.92    2.92    2.92    2.93    2.93"
newtype Parser a = MkP (String -> [(String,a)])


applyParser :: Parser a -> String -> [(String,a)]
applyParser (MkP x) y = x y 


-- (>>=) :: m a -> (a -> m b) -> m b
instance Monad Parser where 
    return x = MkP f
        where
            f inp = [(inp,x)]
    f >>= g = MkP s 
        where
            s inp = [(rest,out) | (firstremain,firstout) <- applyParser f inp, (rest,out) <- applyParser (g firstout) firstremain]



item :: Parser Char
item = MkP f
    where
        f [] = []
        f (x:xs) = [(xs,x)]


zero :: Parser Char
zero = MkP f
    where
        f _ = []

sat :: (Char -> Bool) -> Parser Char
sat predicate = 
    item >>= \x ->
    if predicate x then return x else zero


doParser :: Parser a -> Int -> Parser ()
doParser x count = helper count
    where
        helper count = do
            if count > 0 then do
                x
                helper (count - 1)
            else return ()
numberParser :: Parser Float
numberParser = do
    a <- item
    b <- item
    c <- item
    d <- item
    let number = read [a,b,c,d] :: Float in return number

yieldParser :: Parser [Float]
yieldParser = do
    x <- numberParser
    helper [x] where
        helper y = do 
            a <- randomthing
            helper (y ++ [a])
        randomthing = do
            item
            item
            item
            item
            numberParser




spotrate :: Fractional a => Int -> a
spotrate = \t -> if (t == 1) then 5 else 2

untilParser :: (Char -> Bool) -> Parser [Char]
untilParser p = helper []
    where
        helper x = do
            y <- item
            if p y then helper (x ++ [y]) else return x 

1 个答案:

答案 0 :(得分:0)

helper y = do 
    a <- randomthing
    helper (y ++ [a])
  

什么是随机事件失败

<arandomthing生成空列表时,

>>=永远不会获得值。

如果您查看g的定义,firstout会针对applyParser f inp中的每个结果应用applyParser f inp。因此,如果g结果为零,则f将应用零次。

助手randomthing的定义是g\a -> helper (y ++ [a])g。因此,如果永远不会应用randomthing produces an empty list for the given input)a不是ag没有值,因为applyParser只存在于{{1}}内。< / p>

  

我希望能够检查解析是否失败

使用monadic界面无法做到这一点。相反,您必须自己使用{{1}},然后检查它是否返回空列表。