Antlr4 将整数定义为标记时匹配单个数字时出现问题

Antlr4 将整数定义为标记时匹配单个数字时出现问题,antlr4,Antlr4,我在语法方面遇到了问题。这是简化版。我尝试解析的语言有如下表达式: testing1(2342); testing2(idfor2); testing3(4654); testing4[1..n]; testing5[0..1]; testing6(7); testing7(1); testing8(o); testing9(n); 当我为[1..n]或[0..1]表达式引入规则时,问题就出现了。语法文件(我尝试过的众多变体之一): 当我用这个语法分析样本时,它在testing7(1)上失败和

我在语法方面遇到了问题。这是简化版。我尝试解析的语言有如下表达式:

testing1(2342);
testing2(idfor2);
testing3(4654);
testing4[1..n];
testing5[0..1];
testing6(7);
testing7(1);
testing8(o);
testing9(n);
当我为[1..n]或[0..1]表达式引入规则时,问题就出现了。语法文件(我尝试过的众多变体之一):

当我用这个语法分析样本时,它在
testing7(1)上失败
测试(9)。它匹配为
decMin
decMax
,而不是
Integer
Identifier

line 8:9 mismatched input '1' expecting {Integer, Identifier}
line 10:9 mismatched input 'n' expecting {Integer, Identifier}

我尝试了许多变体,但无法使其正常工作。

我认为您的问题在于没有使用lexer规则明确定义您想要的内容

添加此规则时:

decMin : '0' | '1' ;
实际上,您创建了一个与“0”匹配的未命名词法规则,另一个与“1”匹配:

UNNAMED_0_RULE : '0';
UNNAMED_1_RULE : '1';
您的解析器规则变成:

decMin : UNNAMED_0_RULE | UNNAMED_1_RULE ;
问题:现在,当你的lexer看到 试验7(1); **它看不见** callName'('callParameter')“”;' 再也看不到了 调用名“(“未命名规则”)”;“ 它不明白这一点

这是因为lexer规则在解析器规则之前是有效的

要解决您的问题,请高效地定义lexer规则,它可能如下所示:

grammar test;

/*---------------- PARSER ----------------*/
tests
    : test* 
    ;

test
    : call
    | declaration 
    ;


call
    : callName '(' callParameter ')' ';' 
    ;

callName 
    : identifier 
    ;

callParameter 
    : identifier 
    | integer 
    ;


declaration
    : declarationName '[' declarationParams ']' ';' 
    ;

declarationName 
    : identifier 
    ;

declarationParams
    : decMin '..' decMax 
    ;


decMin 
    : INTEGER_ZERO 
    | INTEGER_ONE
    ;

decMax 
    : INTEGER_ONE
    | LETTER_N
    ;

integer 
    : (INTEGER_ZERO | INTEGER_ONE | INTEGER_OTHERS)+
    ;

identifier
    : LETTER_N
    | IDENTIFIER
    ;

/*---------------- LEXER ----------------*/

LETTER_N:       N;

IDENTIFIER 
    : [a-zA-Z_][a-zA-Z0-9_]*
    ;

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

INTEGER_ZERO:   '0';
INTEGER_ONE:    '1';
INTEGER_OTHERS: '2'..'9';

fragment N: [nN];
我刚刚测试了这个语法,它很有效

缺点是,它将在lexer步骤中切割整数(在lexer规则中将1245切割为1 2 4 5,并且将解析器规则视为1 2 4和5的联合)

我认为最好不要太精确,只写: decMin:整数|标识符


但这取决于你对语法做了什么…

是的!现在可以了。我以前尝试过这样的方法,但真正不同的是将
标识符
整数
转换为规则,而不是词素。
grammar test;

/*---------------- PARSER ----------------*/
tests
    : test* 
    ;

test
    : call
    | declaration 
    ;


call
    : callName '(' callParameter ')' ';' 
    ;

callName 
    : identifier 
    ;

callParameter 
    : identifier 
    | integer 
    ;


declaration
    : declarationName '[' declarationParams ']' ';' 
    ;

declarationName 
    : identifier 
    ;

declarationParams
    : decMin '..' decMax 
    ;


decMin 
    : INTEGER_ZERO 
    | INTEGER_ONE
    ;

decMax 
    : INTEGER_ONE
    | LETTER_N
    ;

integer 
    : (INTEGER_ZERO | INTEGER_ONE | INTEGER_OTHERS)+
    ;

identifier
    : LETTER_N
    | IDENTIFIER
    ;

/*---------------- LEXER ----------------*/

LETTER_N:       N;

IDENTIFIER 
    : [a-zA-Z_][a-zA-Z0-9_]*
    ;

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

INTEGER_ZERO:   '0';
INTEGER_ONE:    '1';
INTEGER_OTHERS: '2'..'9';

fragment N: [nN];