antlr4解决语法歧义
作为帮助我解决解释数字时的歧义的后续行动,我现在进入下一期——数字也被允许作为标识符的一部分,不幸的是,甚至在标识符的开头,所以 这个语法说明了这个问题antlr4解决语法歧义,antlr4,Antlr4,作为帮助我解决解释数字时的歧义的后续行动,我现在进入下一期——数字也被允许作为标识符的一部分,不幸的是,甚至在标识符的开头,所以 这个语法说明了这个问题 grammar NOVIANum; statement : (priorityT | integerT | levelT )* ; priorityT : T_PRIO twoDigits ; integerT : T_INTEGER integer ; levelT : T_LEVEL levelNumber ; levelNu
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' ;
ZERO : '0' ;
OneToFour : [1-4] ;
FiveToNine : [5-9] ;
ID : Letter SeparatorAndLetter* ;
Letter : [a-zA-Z0-9];
SeparatorAndLetter : ([\-]* [_]* Letter+);
以下输入
INTEGER 350
PRIO 10
LEVEL 01
果然结果不错
line 1:8 mismatched input '350' expecting {'0', OneToFour, FiveToNine}
line 2:5 no viable alternative at input '10'
line 3:6 no viable alternative at input '01'
(statement (integerT INTEGER (integer 350)) (priorityT PRIO (twoDigits 10)) (levelT LEVEL (levelNumber 01)))
当解析“350”时,as ID将在整数之前输入
有办法吗
谢谢-Alex将
ID
作为解析器规则而不是词法规则。如果一个ID只能是数字,那么lexer就不可能将其分开,因为您的整数lexer规则只匹配1位数字,所以对于超过1位的数字,lexer总是倾向于使用ID
规则(lexer总是尝试匹配可能最长的输入序列)
以下语法适用于示例输入:
grammar NOVIANum;
statement : (priorityT | integerT | levelT | idT)* ;
priorityT : T_PRIO twoDigits ;
integerT : T_INTEGER integer ;
levelT : T_LEVEL levelNumber ;
idT : T_ID id ;
levelNumber : LVLNUMBER ;
integer : LVLNUMBER | TWODIGITS | NONZERONR ;
twoDigits : LVLNUMBER | TWODIGITS ;
number : LVLNUMBER | TWODIGITS | NONZERONR | ANYNUMBER ;
id : number | STRING ;
WS : [ \t\r\n]+ -> skip ;
T_INTEGER : 'INTEGER' ;
T_LEVEL : 'LEVEL' ;
T_PRIO : 'PRIO' ;
T_ID : 'ID' ;
LVLNUMBER : ZERO (OneToFour | FiveToNine) | OneToFour (ZERO | OneToFour | FiveToNine) ;
TWODIGITS : ZERO ZERO | FiveToNine (ZERO | OneToFour | FiveToNine) ;
NONZERONR : ZERO* (OneToFour | FiveToNine) (ZERO | OneToFour | FiveToNine)* ;
ANYNUMBER : (ZERO | OneToFour | FiveToNine)+ ;
STRING : (LVLNUMBER | TWODIGITS | NONZERONR | ANYNUMBER | LETTER) (Minus* Underscore* (LVLNUMBER | TWODIGITS | NONZERONR | ANYNUMBER | LETTER)+)* ;
fragment LETTER : [a-zA-Z];
fragment Minus : '-' ;
fragment Underscore : '_' ;
fragment ZERO : '0' ;
fragment OneToFour : [1-4] ;
fragment FiveToNine : [5-9] ;
尽管该语法正确地解析了示例输入,但如果您有许多不同的特殊数字,如
LVLNUMBER
或twodights
,则该语法相当笨拙。我更愿意在解析后使用侦听器验证这些值(例如levelNumber<50)。在本例中,Number
lexer规则永远不会匹配。它需要是一个解析器规则number
。多亏了你们两位,现在所有位都在解析器级别,这就导致了另一个问题,即使用“id”作为T_id:'id'代码>idT:T\u ID代码>输入ID1Z
IDMyLevel
会导致行9:0在输入“”处没有可行的替代方案(语句(integerT INTEGER(INTEGER 35 0))(priorityT PRIO(两位数10))(levelT LEVEL(levelnumber 01))(idT ID(ID(number 1)(separatorAndLetter Z))(idT ID(ID M(separatorAndLetter y))(levelT levelnumber))
即,作为Lexer令牌的所有内容现在都将被标识为Lexer令牌,即使它是id的一部分(现在是解析器规则)因此->没有可行的替代方案再次感谢,@ibizarudi,但恐怕还没有雪茄。LEVELX的id可以正常工作,但是LEVEL-X
会导致第10:3行在输入“级别”上没有可行的替代方案第10:8行不匹配的输入“-”期望LvlNumber
(idT id id)(levelT-LEVEL(levelNumber-X)))
再次更新STRING
现在应该匹配任何有效的标识符,而不仅仅是数字,因为它们由上面的四条lexer规则匹配。如果某个标识符恰好与字符串
不匹配,则应编辑此elxer规则以匹配它以使其正常工作。