2011-07-19 51 views
7

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

我知道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 

解决方法是相当难看:

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 

此外,Attoparsec缺少的错误处理。

对于ocamlyacc/ocamllex,Happy/Alex是相当不友好的,BNFC不灵活 并且在我的情况下需要在解析后进行额外的AST遍历。另外,错误处理不是很好。

有三个休息选项:Parsec2,Parsec3和uu-parselib。我发现了一些有争议的基准,假设Parsec2比Parsec3更快,或者UU更快,或者更慢。

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

+1

如果你正在解析“人类大小”的数据(即人们编写的文件),任何主流的解析器组合库应该是很好的速度方式,但你可能不得不注意一些控制回溯你写的解析器。如果你正在解析大量的数据文件,那么方程式会有所变化,我会在这一点上寻找基准,并考虑你可以交换什么样的功能来交换速度(例如源位置跟踪可能会显着减慢)。 –

+1

不是答案,但我已经使用uu-parselib了很多。它功能强大,并具有一些不错的功能,如自动流校正。我唯一的抱怨是,并非所有的功能都立即显而易见,特别是如果你不熟悉解析器。我从来没有遇到速度问题,但我的输入数据大部分都是千字节大小。 –

回答

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

  2. 去年的编程之夏后,parsec3进行了优化,并且不再明显比parsec2慢

  3. 几个语法(中型)年前夫妇我做了测试,发现快乐/亚历克斯,业绩,parsec2/alex,parsec2和polyparse非常接近。 Attoparsec在字节流上速度更快,但我需要多字节。

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

+2

你确定Parsec接近Happy/Alex吗?在这种情况下,根本没有意义使用Happy或BNFC。可能有我可以自己运行的任何基准吗? – voidlizard

+3

无论效率如何,使用像Happy这样的解析器生成器的优点是,您可以获得有关语法(如歧义)的错误和警告。 – augustss

+1

attoparsec-text怎么样? – alternative