[英]Translate Haskell parsec to FParsec
如何翻譯此Haskell代碼:
import Text.ParserCombinators.Parsec((<|>), unexpected, lookAhead, noneOf, char)
import Control.Monad(when)
data BracketElement = BEChar Char | BEChars String | BEColl String | BEEquiv String | BEClass String
p_set_elem_char = do
c <- noneOf "]"
when (c == '-') $ do
atEnd <- (lookAhead (char ']') >> return True) <|> (return False)
when (not atEnd) (unexpected "A dash is in the wrong place in a bracket")
return (BEChar c)
到FParsec? 最好的方法是沒有monadic語法以提供良好的性能。
預先感謝亞歷山大。
對不起,造成誤導。 我稍微糾正了使Haskell代碼可編譯的問題:
import Text.ParserCombinators.Parsec((<|>), (<?>), unexpected, lookAhead, noneOf, char)
import Control.Monad(when)
import Data.Functor.Identity
import qualified Text.Parsec.Prim as PR
-- | BracketElement is internal to this module
data BracketElement = BEChar Char | BEChars String | BEColl String | BEEquiv String | BEClass String
deriving Show
p_set_elem_char :: PR.ParsecT [Char] u Identity BracketElement
p_set_elem_char = do
c <- noneOf "]"
when (c == '-') $ do
atEnd <- (lookAhead (char ']') >> return True) <|> (return False)
when (not atEnd) (unexpected "A dash is in the wrong place in a bracket")
return (BEChar c)
現在可以重現* p_set_elem_char *計算。
我衷心感謝所有幫助我的人。
我做出了自己的近似值,但不幸的是,它並沒有達到預期的功能:
type BracketElement = BEChar of char
| BEChars of string
| BEColl of string
| BEEquiv of string
| BEClass of string
let p_set_elem_char : Parser<BracketElement, _> =
fun stream ->
let stateTag = stream.StateTag
let reply = (noneOf "]") stream
let chr = reply.Result
let mutable reply2 = Reply(BEChar chr)
if reply.Status = Error && stateTag = stream.StateTag then
reply2.Status <- Error
reply2.Error <- reply.Error
else if chr = '-' && stream.Peek() <> ']' then
reply2.Status <- Error
reply2.Error <- messageError ("A dash is in the wrong place in a bracket")
reply2
在toyvo的答案中使用BracketElement
類型,您可以執行以下操作
let pBEChar : Parser<_, unit> =
let c =
pchar '-' .>> followedByL (pchar ']') "A dash is in the wrong place in a bracket"
<|> noneOf "-]"
c |>> BEChar
我對FParsec不太了解,但是這是一個幼稚的嘗試,根據注釋對性能進行了一些糾正:
type BracketElement =
| BEChar of char
| BEChars of string
| BEColl of string
| BEEquiv of string
| BEClass of string
let parseBEChar : Parser<BracketElement,unit> =
let okChars = noneOf "]"
let endTest =
(lookAhead (skipChar ']') >>. parse.Return(true))
<|> parse.Return(false)
let failure = fail "A dash is in the wrong place in a bracket"
parse {
let! c = okChars
if c = '-' then
let! atEnd = endTest
if not atEnd then
return! failure
else
return BEChar c
else
return BEChar c
}
與Daniel提出的類似,您可以將解析器編寫為
let pSetElementChar : Parser<_,unit> =
satisfy (function '-' | ']' -> false | _ -> true)
<|> (pchar '-' .>> followedByString "]")
|>> BEChar
如果要將自定義消息添加到錯誤中,則可以像Daniel的回答中那樣使用followedByL
,也可以使用fail
原語添加消息
let pSetElementChar2 : Parser<_,unit> =
satisfy (function '-' | ']' -> false | _ -> true)
<|> (pchar '-' .>> (followedByString "]"
<|> fail "A dash is in the wrong place in a bracket"))
|>> BEChar
低級別的實現可以很簡單
let pSetElementChar3 : Parser<_,unit> =
fun stream ->
let c = stream.ReadCharOrNewline()
if c <> EOS then
if c <> '-' || stream.Peek() = ']' then Reply(BEChar c)
else Reply(Error, messageError "A dash is in the wrong place in a bracket")
else
Reply(Error, unexpected "end of input")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.