ANTLR能否根据以下字符区分lexer规则?

ANTLR能否根据以下字符区分lexer规则?,antlr,lexer,Antlr,Lexer,为了解析测试文件,我希望允许标识符以数字开头 我的规则是: ID : ('a'..'z' | 'A'..'Z' | '0'..'9' | '_') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')* ; 但是,我还需要匹配此文件中的数字。我的原则是: INT : '0'..'9'+ ; 显然,Antlr不会让我这么做,因为INT永远不会匹配 有没有办法允许这样做?具体地说,我希望匹配一个整数,后跟一

为了解析测试文件,我希望允许标识符以数字开头

我的规则是:

ID  :   ('a'..'z' | 'A'..'Z' | '0'..'9' | '_') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')*
;
但是,我还需要匹配此文件中的数字。我的原则是:

INT :   '0'..'9'+
;
显然,Antlr不会让我这么做,因为INT永远不会匹配

有没有办法允许这样做?具体地说,我希望匹配一个整数,后跟一个ID,不带空格,作为一个ID,并且仅当它后跟一个空格时,才创建一个INT标记

例如:

3BOB -> [ID with text "3BOB"]
3 BOB -> [INT with text "3"] [ID with text "BOB"]

只需更改ID和INT标记的定义顺序

grammar qqq;

// Parser's rules.

root:
    (integer|identifier)+
;

integer:
    INT {System.out.println("INT with text '"+$INT.text+"'.");}
;

identifier:
    ID {System.out.println("ID with text '"+$ID.text+"'.");}
;

// Lexer's tokens.

INT:    '0'..'9'+
;

ID:    ('a'..'z' | 'A'..'Z' | '0'..'9' | '_')
       ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')*
;

WS:    ' ' {skip();}
;

UNPREDICTED_TOKEN
:
    ~(' ') {System.out.println("Unpredicted token.");}
;
语法中标记的定义顺序很重要:如果一个字符串可以归属于多个标记,那么它将归属于首先定义的标记。在您的例子中,如果您希望整数“123”在仍然符合ID的情况下被赋予INT属性,请将INT定义放在第一位

Antlr的令牌匹配是贪婪的,因此它不会在“123BOB”中的“123”上停止,而是将继续,直到没有一个令牌匹配字符串并获取最后一个匹配的令牌。因此,您的标识符现在可以从数字开始


关于令牌顺序的备注也可以在中找到。

只需更改ID和INT令牌的定义顺序即可

grammar qqq;

// Parser's rules.

root:
    (integer|identifier)+
;

integer:
    INT {System.out.println("INT with text '"+$INT.text+"'.");}
;

identifier:
    ID {System.out.println("ID with text '"+$ID.text+"'.");}
;

// Lexer's tokens.

INT:    '0'..'9'+
;

ID:    ('a'..'z' | 'A'..'Z' | '0'..'9' | '_')
       ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')*
;

WS:    ' ' {skip();}
;

UNPREDICTED_TOKEN
:
    ~(' ') {System.out.println("Unpredicted token.");}
;
语法中标记的定义顺序很重要:如果一个字符串可以归属于多个标记,那么它将归属于首先定义的标记。在您的例子中,如果您希望整数“123”在仍然符合ID的情况下被赋予INT属性,请将INT定义放在第一位

Antlr的令牌匹配是贪婪的,因此它不会在“123BOB”中的“123”上停止,而是将继续,直到没有一个令牌匹配字符串并获取最后一个匹配的令牌。因此,您的标识符现在可以从数字开始


您还可以在中找到有关代币顺序的备注。

您的规则中的以下细微更改应该可以起到作用:

ID  :   ('0'..'9')* // optional numbers
        ('a'..'z' | 'A'..'Z' | '_' |  '&' | '/' | '-' | '.') // followed by mandatory character which is not a number
        ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')* // followed by more stuff (including numbers)
;

INT :   '0'..'9'+ // a number
;

您只需允许您的标识符以可选数字开头,并强制使用以下字符。

规则中的以下细微更改即可实现此目的:

ID  :   ('0'..'9')* // optional numbers
        ('a'..'z' | 'A'..'Z' | '_' |  '&' | '/' | '-' | '.') // followed by mandatory character which is not a number
        ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '&' | '/' | '-' | '.')* // followed by more stuff (including numbers)
;

INT :   '0'..'9'+ // a number
;

您只需允许标识符以可选数字开头,并强制使用以下字符。

我不清楚这有什么帮助。这是如何让我的标识符以数字开始的?@chollida,我试着做一个更好的解释,看看它是否有帮助。我不清楚这会有什么帮助。这是怎么让我的标识符从数字开始的?@chollida,我试着做一个更好的解释,看看是否有帮助。