为什么会出现"输入时没有可行的替代方案"?



我编写了以下组合语法:

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可以匹配DIGITMONTH, 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
...

所以它不是DIGITFLOAT -它是MONTH。因此,您的filter规则不匹配。是的,规则的顺序很重要,因为在歧义的情况下,ANTLR会选择第一个规则。

从词法分析器中删除歧义。将月份和类似的符号放入语法规则中。你还有很多其他的地方,比如你的FLOAT使DIGIT不可能独立出现,但你仍然在规则中提到DIGITFLOAT。如果DIGIT在语法层面没有意义,则将其作为一个片段,并在解析器规则中仅使用FLOAT

并且养成使用grun和/或ANTLR插件的习惯,以确保您知道您的词法分析器和解析器实际看到的内容。

在这里进行测试时,我看到将FLOAT定义令牌放在DATE定义之前,问题就消失了。

...
FLOAT: DIGIT+ (POINT DIGIT+)?;
DATE: DIGIT DIGIT? SEPARATOR MONTH SEPARATOR DIGIT DIGIT (DIGIT DIGIT)?;
...

我不知道为什么。顺序重要吗?

相关内容

  • 没有找到相关文章

最新更新