0

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

我的规则是:

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"]
4

2 回答 2

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”在仍符合 ID 的情况下归因于 INT - 首先将 INT 定义。

Antlr 的令牌匹配是贪婪的,因此它不会在 '123BOB' 中的 '123' 处停止,而是会继续直到没有令牌匹配字符串并取最后一个匹配的令牌。所以你的标识符现在可以以数字开头。

也可以在Mark Volkmann 的这篇文章中找到关于代币订单的评论。

于 2011-05-04T14:27:41.557 回答
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
;

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

于 2011-05-05T22:22:55.710 回答