我尝试在小于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)))
它需要大约一百秒。这比我希望的慢了三个数量级。有没有办法加快速度,某种方式来调整语法或某些我错过的选项?
答案 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,这有助于了解您自己的问题,并可能找出最适合您的问题。