有什么方法可以加速instaparse?

时间:2016-04-12 12:16:36

标签: clojure instaparse

我尝试在小于700k的dimacs文件上使用instaparse,语法如下

<file>=<comment*> <problem?> clause+
comment=#'c.*'
problem=#'p\s+cnf\s+\d+\s+\d+\s*'
clause=literal* <'0'>
<literal>=#'[1-9]\d*'|#'-\d+'

这样打电话

(def parser
  (insta/parser (clojure.java.io/resource "dimacs.bnf") :auto-whitespace :standard))
...
(time (parser (slurp filename)))

它需要大约一百秒。这比我希望的慢了三个数量级。有没有办法加快速度,某种方式来调整语法或某些我错过的选项?

2 个答案:

答案 0 :(得分:2)

语法错了。它不能满足。

  • 每个file都以clause结尾。
  • 每个clause都以'0'结尾。
  • literal中的clause,即greedy reg-exp,会吃掉 最后的'0'

结论:永远不会找到clause

例如......

=> (parser "60")
Parse error at line 1, column 3:
60
  ^
Expected one of:
"0"
#"\s+"
#"-\d+"
#"[1-9]\d*"

我们可以解析literal

=> (parser "60" :start :literal)
("60")

...但不是clause

=> (parser "60" :start :clause)
Parse error at line 1, column 3:
60
  ^
Expected one of:
"0" (followed by end-of-string)
#"\s+"
#"-\d+"
#"[1-9]\d*"

为什么这么慢?

如果有comment

  • 它可以吞下整个文件;
  • 或在任何'c'个字符中分成连续的comment s;
  • 或在初始'c' 之后的任何时候终止

这意味着必须将每个尾部呈现给语法的其余部分,其中包括Instaparse无法看到内部的literal的reg-exp。因此必须全部尝试,一切都将最终失败。难怪它很慢。

我怀疑这个文件实际上分为。而且你的问题来自于尝试将换行符与其他形式的空白区域混淆。

我可以轻轻地指出,玩一些小例子 - 这就是我所做的 - 可能会给你带来麻烦。

答案 1 :(得分:0)

我认为你对*的广泛使用导致了这个问题。你的语法太模糊/野心勃勃(我猜)。我会检查两件事:

;;run it as
 (insta/parses grammar input)
;; with a small input

这将显示你的语法定义有多么含糊不清:check&#34;含糊不清的语法&#34;。

阅读Engelberg performance notes,这有助于了解您自己的问题,并可能找出最适合您的问题。