簡體   English   中英

haskell parsec(<|>)運算符的行為?

[英]behaviors of the (<|>) operator of haskell parsec?

我想使用RPN解釋器來練習Parsec的使用,這是我的代碼:

module RPN where
import Control.Applicative hiding((<|>))
import Text.ParserCombinators.Parsec 
data RPNVal = Add|Sub|Mul|Div|Num Double deriving(Show)
a <:> b  = (:) <$> a <*> b
a <++> b = (++) <$> a <*> b
opSymbol = oneOf "+-*/"
number   = many1 digit :: Parser String
plus     = char '+' *> number
minus    = char '-' <:> number
integer  = (number <|> minus <|> plus) :: Parser String
float    = integer <++> decimal <++> exponent
    where decimal  = option "" $ char '.' <:> number
          exponent = option "" $ oneOf "eE" <:> number
parseOp :: Parser RPNVal
parseOp = do
    op <- opSymbol
    case op of 
         '+' -> return Add 
         '-' -> return Sub 
         '*' -> return Mul 
         '/' -> return Div
parseNum :: Parser RPNVal
parseNum = liftA (read::String->Double) float >>= return.Num
parseRPNVal :: Parser RPNVal 
-- parseRPNVal = parseOp <|> parseNum
-- parseRPNVal = parseNum <|> parseOp
parseRPNVal = try parseNum <|> parseOp
parseExpr :: Parser [RPNVal]
parseExpr = parseRPNVal `sepBy1` spaces
readExpr :: String->[RPNVal]
readExpr input = case parse parseExpr "RPN" input of
                      Left errMsg -> error $ show errMsg
                      Right val   -> val

parseRPNVal的定義中,我發現如果我使用parseRPNVal = parseOp <|> parseNum ,則解析器運行良好,但是,如果我使用parseRPNVal = parseNum <|> parseOp ,則該函數只能解析數字,而運算符會導致錯誤。

真實世界的Haskell中 ,它說:

該運算符的行為是這樣的:它將首先嘗試左側的解析器。 如果不消耗任何輸入[35],它將嘗試右側的解析器

所以有人可以向我解釋parseOpparseNum的行為嗎?

就像真實世界的Haskell所說的那樣。

parseNum首先解析一個integer ,但是integer -s可以以+-為前綴。

因此,在解析parseNum <|> parseOp ,如果下一個字符是+- ,而我們實際擁有的是一個運算符,則parseNum會讀取該字符,並且此后才會失敗。

使用parseOp <|> parseNum ,當然不需要回溯,因為parseOp只需要parseOp一個字符即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM