簡體   English   中英

將Haskell parsec轉換為FParsec

[英]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.

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