Parser Combinators首选库(haskell)

voi*_*ard 7 parsing haskell

是否有任何解析器组合库可以提供与Happy/Alex相媲美的性能?

我知道Attoparsec,但有时它运行得不好,如下例所示:

isToken c = isLetter c || isDigit c

symbol :: Parser Expr
symbol = do 
    c    <- skipSpace >> satisfy isLetter 
    rest <- takeWhile isToken
    let token = C.cons c rest  -- oops... O(N)
    error $ show token
Run Code Online (Sandbox Code Playgroud)

解决方法非常难看:

do { skipSpace; bs <- scan go True; when (null bs) (fail "Not a symbol"); return bs}
    where go True  c = if isLetter c then Just  False else Nothing
          go False c = if isToken c then Just Fasle else Nothing
Run Code Online (Sandbox Code Playgroud)

此外,Attoparsec缺乏错误处理.

与ocamlyacc/ocamllex相比,Happy/Alex非常不友好(对我而言),BNFC不灵活,在我的情况下需要在解析后进行额外的AST遍历.此外,错误处理不是很好.

休息选项有三种:Parsec2,Parsec3和uu-parselib.假设Parsec2比Parsec3快,或者UU更快,或者速度更慢,我发现了许多有争议的基准.

但要选择什么?有没有人有使用uu-parselib的经验?我需要解析器用于某种DSL,需要足够快的解析才能在将来不改变它.

ADE*_*Ept 7

  1. 还有另一种选择:polyparse.

  2. 在去年的GSoC之后,parsec3进行了优化,不再明显慢于parsec2

  3. 几年前我已经对几个语法(中等大小)进行了测试,发现happy/alex,parsec2/alex,parsec2和polyparse的表现非常接近.Attoparsec在字节流上速度更快,但我需要多字节.

我的建议:看看替代方案处理内部和用户定义的状态并报告错误的方式,并根据这些标准进行选择.

  • 无论效率如何,使用像Happy这样的解析器生成器都有一个优点,就是你会得到关于语法的错误和警告(比如歧义). (3认同)
  • 你确定Parsec接近Happy/Alex吗?在这种情况下,根本不使用Happy或BNFC.也许我可以自己运行任何基准测试? (2认同)