如何翻译这个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
答案 0 :(得分:3)
在toyvo的答案中使用BracketElement
类型,您可以执行类似
let pBEChar : Parser<_, unit> =
let c =
pchar '-' .>> followedByL (pchar ']') "A dash is in the wrong place in a bracket"
<|> noneOf "-]"
c |>> BEChar
答案 1 :(得分:2)
我不太了解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
}
答案 2 :(得分:2)
与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")