是否有任何解析器组合库可以提供与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,需要足够快的解析才能在将来不改变它.
还有另一种选择:polyparse.
在去年的GSoC之后,parsec3进行了优化,不再明显慢于parsec2
几年前我已经对几个语法(中等大小)进行了测试,发现happy/alex,parsec2/alex,parsec2和polyparse的表现非常接近.Attoparsec在字节流上速度更快,但我需要多字节.
我的建议:看看替代方案处理内部和用户定义的状态并报告错误的方式,并根据这些标准进行选择.