ANTLR可以根据以下字符区分词法规则吗?

时间:2011-04-06 18:02:12

标签: antlr lexer

为了解析测试文件,我想让标识符以数字开头。

我的规则是:

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

但是我也需要匹配此文件中的数字。我的理由是:

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

显然Antlr不允许我这样做,因为INT永远不会匹配。

有没有办法允许这个?具体来说,我想匹配一个INTEGER,后跟一个ID,没有空格只是一个ID,只有当后面跟一个空格时才创建一个INT令牌。

例如:

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

2 个答案:

答案 0 :(得分:2)

只需更改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'归为INT,当它仍然符合ID时 - 首先放置INT定义。

Antlr的令牌匹配是贪婪的,因此它不会在'123BOB'中的'123'上停止,但会一直持续直到非令牌匹配字符串并使最后一个令牌匹配。所以你的标识符现在可以从数字开始。

也可以在this article by Mark Volkmann中找到关于令牌订单的评论。

答案 1 :(得分:1)

您的规则中的以下微小变化应该可以解决问题:

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
;

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