【问题】
之前已经写好的一个antlr的.g语法文件,当时在antlrworks中编译都正常的。
现在重新去编译,结果倒出错了:
对应的log:
[13:08:51] error(204): xxx.g:427:29: duplicate token type COMPOSITE_OPERATOR when collapsing subrule into set As a result, alternative(s) 2 were disabled for that input |
【解决过程】
1.看起来,是新添加的token,即那个
COMPOSITE_OPERATOR
惹的祸。
然后去看看代码是:
OPERATOR : '!' | '#' | '$' | '%' | '&' | '*' | '+' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '\\' | '^' | '`' | '|' | '~' ; COMPOSITE_OPERATOR : '==' | '!=' | '<=' | '>=' | '&&' | '||' | '++' | '--' | '<<' | '>>' | '+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '^=' | '|='; //fragment direct_value : (DECIMAL_VALUE | HEX_VALUE);
对应的,看起来COMPOSITE_OPERATOR的语法图,也的确有问题:
其中,<<=和>>=被分解成单个字符了。
而不是我们所想要的,成为一个整体。
2.所以,去改为:
COMMA : ',' ; COMPOSITE_OPERATOR : '<<=' | '>>=' | '==' | '!=' | '<=' | '>=' | '&&' | '||' | '++' | '--' | '<<' | '>>' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|='; OPERATOR : '!' | '#' | '$' | '%' | '&' | '*' | '+' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '\\' | '^' | '`' | '|' | '~' ; //fragment direct_value : (DECIMAL_VALUE | HEX_VALUE);
然后结果是:
第一次编译:
Generate->Generate Code
是正常的:
但是再次去编译:
Generate->Generate Code
结果就出错了:
所以,感觉还是很诡异。
3.还是很奇怪的是:
当手动重新:
删除掉output文件夹;
重新打开Antlrworks
重新编译
结果就是可以的。
如果再次编译,或者是只是删除output文件夹,但不关闭antlrworks,结果重新编译,还是会存在同样的错误。
貌似antlrworks本身对于配置方面,或者编译方面的东西,是有全局的系统的缓存或配置的。
4.然后在代码中,去除掉COMPOSITE_OPERATOR,然后就是正常的了:
无论怎么重复编译,也都不会出错的。
5.后来的后来,是把原先的:
...... COMMA : ',' ; COMPOSITE_OPERATOR : '<<=' | '>>=' | '==' | '!=' | '<=' | '>=' | '&&' | '||' | '++' | '--' | '<<' | '>>' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|='; OPERATOR : '!' | '#' | '$' | '%' | '&' | '*' | '+' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '\\' | '^' | '`' | '|' | '~' ; ...... any_char: ((~('{' | '}')) | COMPOSITE_OPERATOR)+; ......
改为:
...... COMMA : ',' ; COMPOSITE_OPERATOR : '<<=' | '>>=' | '==' | '!=' | '<=' | '>=' | '&&' | '||' | '++' | '--' | '<<' | '>>' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|='; OPERATOR : '!' | '#' | '$' | '%' | '&' | '*' | '+' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '\\' | '^' | '`' | '|' | '~' ; ...... //any_char: ((~('{' | '}')) | COMPOSITE_OPERATOR)+; any_char: (~('{' | '}') | COMPOSITE_OPERATOR)+; ......
就可以了。
6.所以,看来还是自己的语法写的不对。
但是,至于为何:
any_char: ((~('{' | '}')) | COMPOSITE_OPERATOR)+;
会导致:
duplicate token type COMPOSITE_OPERATOR when collapsing subrule into set |
的错误,而:
any_char: (~('{' | '}') | COMPOSITE_OPERATOR)+;
不会导致错误。
至今,还是没有完全搞懂。
7.后来,经过多次再次测试,发现不是上述原因,而是:
还是会,无故的,导致:
duplicate token type COMPOSITE_OPERATOR when collapsing subrule into set |
的错误。
8.现在基本判断出,antlrworks有个全局的缓存。
因为此处,现在是,即使改动antlrworks的文件,然后去重新Generate Code,结果antlrworks都不会重新去编译代码,而是直接报错。
9.后来找到了,antlrworks2缓存(数据)
先不管和此处的antlrworks是否有关,先删除试试。
结果错误依旧。
10.参考:
[antlr-interest] Bug? duplicate token type … when collapsing subrule into set
貌似说这个antlr本身的bug。
11。参考:
提到了,意思是,本身你前面的语法,所表示的内容,已经包含了后面的了,
所以,去看了看自己的语法:
any_char: ((~('{' | '}')) | COMPOSITE_OPERATOR)+;
好像也是这个问题:
本身
~('{' | '}')
其实就已经包含了:
COMPOSITE_OPERATOR
了。
所以去改为:
//any_char: (~('{' | '}'))+; //any_char: ((~('{' | '}')) | COMPOSITE_OPERATOR)+; //any_char: (~('{' | '}') | COMPOSITE_OPERATOR)+; any_char: (COMPOSITE_OPERATOR | (~('{' | '}')) )+;
然后就可以了。
即:
无论如何编译:
是直接编译,还是多次再次编译
还是debug后再去编译
还是编译后再去debug
等等,都是可以正常执行了。不会报错了。
所以,至此,终于解决了这个问题了。
【总结】
当antlr编译出现:
duplicate token type xxx when collapsing subrule into set |
的错误时,则去找到出错的位置。
去查看对应的语法代码,是不是出现了,类似于:
some_rule: TOKEN_A | TOKEN_B;
的语法,并且是TOKEN_A本身耳朵含义,本身所包含的内容,就已经把TOKEN_B中的内容包含在内了。
两个例子:
1.Parsing a log file with ANTLR
错误的写法:
fragment SPECIAL : ( ~'\n' | '\'' | '.' | '(' | ')' | '-');
错误原因:
~'\n' |
本身就已经包含了
'\'' | '.' | '(' | ')' | '-' |
正确的写法:
fragment SPECIAL : ~('\n' | '\'' | '.' | '(' | ')' | '-');
2.我这里的:
错误的写法:
COMPOSITE_OPERATOR : '<<=' | '>>=' | '==' | '!=' | '<=' | '>=' | '&&' | '||' | '++' | '--' | '<<' | '>>' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|='; any_char: ((~('{' | '}')) | COMPOSITE_OPERATOR)+;
错误原因:
~(‘{‘ | ‘}’) |
本身就已经包含了:
COMPOSITE_OPERATOR |
的内容了。
正确的写法:
COMPOSITE_OPERATOR : '<<=' | '>>=' | '==' | '!=' | '<=' | '>=' | '&&' | '||' | '++' | '--' | '<<' | '>>' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|='; any_char: (COMPOSITE_OPERATOR | (~('{' | '}')) )+;
至此,大功告成。
转载请注明:在路上 » 【已解决】Antlr语法编译出错:Cannot generate the grammar because, duplicate token type COMPOSITE_OPERATOR when collapsing subrule into set