我编写了以下组合语法:
grammar KeywordGrammar;
options{
TokenLabelType = MyToken;
}
//start rule
start: sequence+ EOF;
sequence: keyword filter?;
filter: simpleFilter | logicalFilter | rangeFilter;
logicalFilter: andFilter | orFilter | notFilter;
simpleFilter: lessFilter | greatFilter | equalFilter | containsFilter;
andFilter: simpleFilter AND? simpleFilter;
orFilter: simpleFilter OR simpleFilter;
lessFilter: LESS (DIGIT | FLOAT|DATE);
notFilter: NOT IN? (STRING|ID);
greatFilter: GREATER (DIGIT|FLOAT|DATE);
equalFilter: EQUAL (DIGIT|FLOAT|DATE);
containsFilter: EQUAL (STRING|ID);
rangeFilter: RANGE? DATE DATE? | RANGE? FLOAT FLOAT?;
keyword: ID | STRING;
DATE: DIGIT DIGIT? SEPARATOR MONTH SEPARATOR DIGIT DIGIT (DIGIT DIGIT)?;
MONTH: JAN
| FEV
| MAR
| APR
| MAY
| JUN
| JUL
| AUG
| SEP
| OCT
| NOV
| DEC
;
JAN : 'janeiro'|'jan'|'01'|'1';
FEV : 'fevereiro'|'fev'|'02'|'2';
MAR : 'março'|'mar'|'03'|'3';
APR : 'abril' |'abril'|'04'|'4';
MAY : 'maio'| 'mai'| '05'|'5';
JUN : 'junho'|'jun'|'06'|'6';
JUL : 'julho'|'jul'|'07'|'7';
AUG : 'agosto'|'ago'|'08'|'8';
SEP : 'setembro'|'set'|'09'|'9';
OCT : 'outubro'|'out'|'10';
NOV : 'novembro'|'nov'|'11';
DEC : 'dezembro'|'dez'|'12';
SEPARATOR: '/'|'-';
AND: ('e'|'E');
OR: ('O'|'o')('U'|'u');
NOT: ('N'|'n')('Ã'|'ã')('O'|'o');
IN: ('E'|'e')('M'|'m');
GREATER: '>' | ('m'|'M')('a'|'A')('i'|'I')('o'|'O')('r'|'R') ;
LESS: '<' | ('m'|'M')('e'|'E')('n'|'N')('o'|'O')('r'|'R');
EQUAL: '=' | ('i'|'I')('g'|'G')('u'|'U')('a'|'A')('l'|'L');
RANGE: ('e'|'E')('n'|'N')('t'|'T')('r'|'R')('e'|'E');
FLOAT: DIGIT+ | DIGIT+ POINT DIGIT+;
ID: (LETTER|DIGIT+ SYMBOL) (LETTER|SYMBOL|DIGIT)*;
STRING: '"' ( ESC_SEQ | ~('\'|'"') )* '"';
DIGIT: [0-9];
WS: (' '
| 't'
| 'r'
| 'n') -> skip
;
POINT: '.' | ',';
fragment
LETTER: 'A'..'Z'
| 'a'..'z'
| 'u00C0'..'u00D6'
| 'u00D8'..'u00F6'
| 'u00F8'..'u02FF'
| 'u0370'..'u037D'
| 'u037F'..'u1FFF'
| 'u200C'..'u200D'
| 'u2070'..'u218F'
| 'u2C00'..'u2FEF'
| 'u3001'..'uD7FF'
| 'uF900'..'uFDCF'
| 'uFDF0'..'uFFFD'
;
fragment
SYMBOL: '-' | '_';
fragment
HEX_DIGIT: ('0'..'9'|'a'..'f'|'A'..'F');
fragment
ESC_SEQ: '\' ('b'|'t'|'n'|'f'|'r'|'"'|'''|'\')
| UNICODE_ESC
| OCTAL_ESC
;
fragment
OCTAL_ESC: '\' ('0'..'3') ('0'..'7') ('0'..'7')
| '\' ('0'..'7') ('0'..'7')
| '\' ('0'..'7')
;
fragment
UNICODE_ESC: '\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT;
但是在输入时出现no viable alternative at input错误,仅在尝试解析以下类型的句子时发生:关键字OPERATOR DIGIT;例如:
- filter = 2
- 滤波器& lt;2
- filter> 2
0作为一个值,它工作!!
错误在哪里?
谢谢你的帮助,
Yenier
您的词法分析器规则中有很多歧义。在您的情况下,数字1-9
可以匹配DIGIT
和MONTH
, JAN
等。数字0
不受此问题的影响。使用grun
和-tokens
来诊断您遇到的问题:
$ grun KeywordGrammar start -tokens
filter = 0
[@0,0:5='filter',<24>,1:0]
[@1,7:7='=',<21>,1:7]
[@2,9:9='0',<23>,1:9]
[@3,11:10='<EOF>',<-1>,2:0]
$ grun KeywordGrammar start -tokens
filter = 2
[@0,0:5='filter',<24>,1:0]
[@1,7:7='=',<21>,1:7]
[@2,9:9='2',<1>,1:9]
[@3,11:10='<EOF>',<-1>,2:0]
line 1:9 no viable alternative at input '=2'
可以看到,第一种情况下0
的令牌类型为<23>
,第二种情况下2
的令牌类型为<1>
。查看生成的KeywordGrammar.tokens
:
MONTH=1
JAN=2
...
FLOAT=23
...
所以它不是DIGIT
或FLOAT
-它是MONTH
。因此,您的filter
规则不匹配。是的,规则的顺序很重要,因为在歧义的情况下,ANTLR会选择第一个规则。
从词法分析器中删除歧义。将月份和类似的符号放入语法规则中。你还有很多其他的地方,比如你的FLOAT
使DIGIT
不可能独立出现,但你仍然在规则中提到DIGIT
和FLOAT
。如果DIGIT
在语法层面没有意义,则将其作为一个片段,并在解析器规则中仅使用FLOAT
。
并且养成使用grun
和/或ANTLR插件的习惯,以确保您知道您的词法分析器和解析器实际看到的内容。
在这里进行测试时,我看到将FLOAT定义令牌放在DATE定义之前,问题就消失了。
...
FLOAT: DIGIT+ (POINT DIGIT+)?;
DATE: DIGIT DIGIT? SEPARATOR MONTH SEPARATOR DIGIT DIGIT (DIGIT DIGIT)?;
...
我不知道为什么。顺序重要吗?