Antlr4 重叠规则-输入不匹配

Antlr4 重叠规则-输入不匹配,antlr4,lexer,Antlr4,Lexer,我的语法(如下所示(从原始语法中删减))需要一些重叠的规则 grammar NOVIANum; statement : (priorityStatement | integerStatement)* ; priorityStatement : T_PRIO TwoDigits ; integerStatement : T_INTEGER Integer ; WS : [ \t\r\n]+ -> skip ; T_PRIO : 'PRIO' ; T_INTEGER : 'INTE

我的语法(如下所示(从原始语法中删减))需要一些重叠的规则

grammar NOVIANum;

statement :  (priorityStatement | integerStatement)* ;

priorityStatement : T_PRIO TwoDigits ;

integerStatement : T_INTEGER Integer ;

WS : [ \t\r\n]+ -> skip ;

T_PRIO : 'PRIO' ;
T_INTEGER : 'INTEGER' ;

Integer: OneToNine Digit*  |  ZERO  ;

TwoDigits : Digit Digit ;

fragment OneToNine : ('1'..'9') ;

fragment Digit: ('0'..'9');

ZERO : [0] ;
所以“整数”和“两位数”有一定程度的重叠

以下输入

INTEGER 10
PRIO 10
导致

line 2:5 mismatched input '10' expecting TwoDigits
[@0,0:6='INTEGER',<2>,1:0]
[@1,8:8='3',<5>,1:8]
[@2,9:9='5',<5>,1:9]
[@3,10:10='0',<6>,1:10]
[@4,12:15='PRIO',<4>,2:0]
[@5,17:17='1',<5>,2:5]
[@6,18:18='0',<6>,2:6]
[@7,20:24='LEVEL',<3>,3:0]
[@8,26:26='0',<6>,3:6]
[@9,27:27='1',<5>,3:7]
[@10,29:33='LEVEL',<3>,4:0]
[@11,35:35='0',<6>,4:6]
[@12,36:36='5',<5>,4:7]
[@13,38:42='LEVEL',<3>,5:0]
[@14,44:44='1',<5>,5:6]
[@15,45:45='0',<6>,5:7]
[@16,47:51='LEVEL',<3>,6:0]
[@17,53:53='4',<5>,6:6]
[@18,54:54='9',<5>,6:7]
[@19,55:54='<EOF>',<-1>,6:8]
line 5:6 no viable alternative at input '1'
line 6:6 no viable alternative at input '4'
(statement (integerT INTEGER (integer 3 5 0)) (priorityT PRIO (twoDigits 1 0)) (levelT LEVEL (levelNumber 0 1)) (levelT LEVEL (levelNumber 0 5)) (levelT LEVEL (levelNumber 1 0)) (levelT LEVEL (levelNumber 4 9)))
当整数在两位数字之前且在

line 1:8 mismatched input '10' expecting Integer
当语法中整数前面有两位数时

有办法解决这个问题吗

谢谢-亚历克斯

编辑:

谢谢@GRosenberg,当然,你的建议对这个小例子很有效,但当我将它整合到我的完整语法中时,肯定会导致不同的输入错误

原因是另一个lexer规则需要范围为“[1-4]”,所以我想我会很聪明,把它变成

grammar NOVIANum;

statement :  (priorityT | integerT | levelT )* ;

priorityT : T_PRIO twoDigits ;

integerT : T_INTEGER integer ;

levelT : T_LEVEL levelNumber  ;

levelNumber : ( ZERO DIGIT ) | ( OneToFour (ZERO | DIGIT) ) ;

integer: ZERO*  ( DIGIT ( DIGIT | ZERO )* ) ;

twoDigits : (ZERO | DIGIT) ( ZERO | DIGIT ) ;

oneToFour : OneToFour (DIGIT | ZERO) ;

WS : [ \t\r\n]+ -> skip ;

T_INTEGER : 'INTEGER' ;
T_LEVEL   : 'LEVEL' ;
T_PRIO    : 'PRIO' ;

DIGIT: OneToFour | FiveToNine ;

ZERO : '0' ;

OneToFour  : [1-4] ;
FiveToNine : [5-9] ;
这仍然适用于以前的输入,但

INTEGER 350
PRIO 10
LEVEL 01
LEVEL 05
LEVEL 10
LEVEL 49
导致

line 2:5 mismatched input '10' expecting TwoDigits
[@0,0:6='INTEGER',<2>,1:0]
[@1,8:8='3',<5>,1:8]
[@2,9:9='5',<5>,1:9]
[@3,10:10='0',<6>,1:10]
[@4,12:15='PRIO',<4>,2:0]
[@5,17:17='1',<5>,2:5]
[@6,18:18='0',<6>,2:6]
[@7,20:24='LEVEL',<3>,3:0]
[@8,26:26='0',<6>,3:6]
[@9,27:27='1',<5>,3:7]
[@10,29:33='LEVEL',<3>,4:0]
[@11,35:35='0',<6>,4:6]
[@12,36:36='5',<5>,4:7]
[@13,38:42='LEVEL',<3>,5:0]
[@14,44:44='1',<5>,5:6]
[@15,45:45='0',<6>,5:7]
[@16,47:51='LEVEL',<3>,6:0]
[@17,53:53='4',<5>,6:6]
[@18,54:54='9',<5>,6:7]
[@19,55:54='<EOF>',<-1>,6:8]
line 5:6 no viable alternative at input '1'
line 6:6 no viable alternative at input '4'
(statement (integerT INTEGER (integer 3 5 0)) (priorityT PRIO (twoDigits 1 0)) (levelT LEVEL (levelNumber 0 1)) (levelT LEVEL (levelNumber 0 5)) (levelT LEVEL (levelNumber 1 0)) (levelT LEVEL (levelNumber 4 9)))
在不该踢的地方踢,即使在这种组合形式下, 所以,我能想到的唯一解决办法是

grammar NOVIANum;

statement :  (priorityT | integerT | levelT )* ;

priorityT : T_PRIO twoDigits ;

integerT : T_INTEGER integer ;

levelT : T_LEVEL levelNumber  ;

levelNumber : ( ZERO (OneToFour | FiveToNine) | ( OneToFour (ZERO | (OneToFour | FiveToNine)) ) ) ;

integer: ZERO*  ( (OneToFour | FiveToNine) ( (OneToFour | FiveToNine) | ZERO )* ) ;

twoDigits : (ZERO | (OneToFour | FiveToNine)) ( ZERO | (OneToFour | FiveToNine) ) ;

WS : [ \t\r\n]+ -> skip ;

T_INTEGER : 'INTEGER' ;
T_LEVEL   : 'LEVEL' ;
T_PRIO    : 'PRIO' ;

// DIGIT: OneToFour | FiveToNine;

ZERO : '0' ;

OneToFour  : [1-4] ;
FiveToNine : [5-9] ;
因为当我为它创建解析器规则时

oneToNine : OneToFour | FiveToNine ;
它会给我这个

integerT INTEGER (integer (oneToNine 3) (oneToNine 5) 0))
这是丑陋的,更难处理,而不仅仅是

(integerT INTEGER (integer 3 5 0))

作为设计的一般问题,始终尝试在同一级别使用区分元素及其对象(T_PRIO->twodights),解析器或词法分析器。假定
整数
两位数
规则的语义性质很重要,将它们提升到解析器,让词法分析器只生成数字。也就是说,不要过度约束lexer

在解析器中,您可以让
整数
规则在功能上隐藏
两位数
规则,除非在计算
优先级语句
规则时:

priorityStatement : T_PRIO twoDigits ;

integerStatement : T_INTEGER integer ;

integer: ZERO | ( DIGIT ( DIGIT | ZERO )* ) ;

twoDigits : DIGIT DIGIT ;

T_PRIO : 'PRIO' ;
T_INTEGER : 'INTEGER' ;
DIGIT : [1-9] ;
ZERO : '0' ;

但是从lexer中跳过空格,导致解析器可能将像
“12”
(数字、空格、数字)这样的输入作为单个
整数进行匹配。和
“12”
可以匹配为
两位数。