是否有建议的做法来标记大型备用规则?
我认为这基本上是一件好事,你可以得到";"免费";,但在一些非常基本的测试中,它有两个解析表达式的基本文件——一个有表达式,一个没有表达式——性能很差,而且大小几乎大了50%。
以下是我用于测试的两种语法:
grammar YesLabels;
root: (expr ';')* EOF;
expr
: '(' expr ')' # ParenExpr
| '-' expr # UMinusExpr
| '+' expr # UPlusExpr
| expr '*' expr # TimesExpr
| expr '/' expr # DivExpr
| expr '-' expr # MinusExpr
| expr '+' expr # PlusExpr
| Atom # AtomExpr
;
Atom:
[a-z]+ | [0-9]+ | ''' Atom '''
;
WHITESPACE: [ trn] -> skip;
grammar NoLabels;
root: (expr ';')* EOF;
expr
: '(' expr ')'
| '-' expr
| '+' expr
| expr '*' expr
| expr '/' expr
| expr '-' expr
| expr '+' expr
| Atom
;
Atom:
[a-z]+ | [0-9]+ | ''' Atom '''
;
WHITESPACE: [ trn] -> skip;
在以下表达式上测试(重复100k次,~2MB文件(:
1+1-2--(2+3/2-5)+4;
我得到以下时间和大小:
$ ant YesLabels root ../tests/expr.txt
real 0m1.096s # varies quite a bit, sometimes larger than the other
116K ./out
$ ant NoLabels root ../tests/expr.txt
real 0m0.821s # varies quite a bit, sometimes smaller than the other
80K ./out
因此,当您使用带标签的备选方案时,您将获得更多的类。这就是(IMHO(的优点,它使侦听器更容易定位,并且每个类都更简单,其属性仅适用于该备选方案。
虽然这意味着可执行文件将更大,具有有意义的解析树大小,但目标类实例的内存节省可能会弥补可执行文件大小的差异。(在您的示例中,差异为46K,这与实际运行程序的解析树、令牌流等使用的内存相比,在内存方面没有任何区别。
您的示例输入可能不够大,无法真正显示任何性能差异,但是,正如其他地方所提到的,您应该首先关注可用的解析树,然后在确定这实际上是一个问题时解决大小/性能问题。
并非所有人都同意,但在我看来,标记的替代品的好处是巨大的,空间/性能需求可以忽略不计(如果可以测量的话(