ANTLR:令牌的组合

ANTLR:令牌的组合,antlr,Antlr,我有一个问题,我正在搜索大约一个小时。给定的ANTLR lexer规则由2个(或更多)子规则组成。Lexer现在生成单独的AST节点 例如: [...] variable: '$' CamelCaseIdentifier; CamelCaseIdentifier: ('a'..'z') Identifier*; Identifier: ('a'..'z' | 'A' .. 'Z' | '0'..'9')+; [...] 给定的[…]$a[…]输入结果是..,$,a,… 我正在寻找一种方法来告诉

我有一个问题,我正在搜索大约一个小时。给定的ANTLR lexer规则由2个(或更多)子规则组成。Lexer现在生成单独的AST节点

例如:

[...]
variable: '$' CamelCaseIdentifier;
CamelCaseIdentifier: ('a'..'z') Identifier*;
Identifier: ('a'..'z' | 'A' .. 'Z' | '0'..'9')+;
[...]
给定的
[…]$a[…]
输入结果是
..,$,a,…

我正在寻找一种方法来告诉lexer,这些规则不应该分开:
…$a,…


有人能帮我吗?

也许可以尝试将所有规则名称都大写

编辑:以示例为例

grammar Dummy;

prog : VARIABLE*;

VARIABLE: '$' CAMELCASEIDENTIFIER;
CAMELCASEIDENTIFIER: ('a'..'z') IDENTIFIER*;
IDENTIFIER: ('a'..'z' | 'A' .. 'Z' | '0'..'9')+;


WS: (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN; };

解析器规则以小写字母开头,lexer规则以大写字母开头。当您作为AST输出时,解析器规则中的每个单独标记都将成为一个单独的节点,因此您需要将
变量
规则设置为lexer规则,而不是解析器规则:

Variable            : '$' CamelCaseIdentifier;
CamelCaseIdentifier : ('a'..'z') Identifier*;
Identifier          : ('a'..'z' | 'A' .. 'Z' | '0'..'9')+;
但是如果您这样做,输入
123456
将被标记为
标识符,这可能不是您想要的。此外,
Identifier
规则最好命名为
AlphaNum
。如果你对它做了一个片段规则,你就要确保lexer不会在自己身上产生任何
AlphaNum
标记,而只会对其他lexer规则使用
AlphaNum
(比如你的
CamelCaseIdentifier
规则)。如果还需要与
标识符匹配的规则,请执行以下操作:

Variable            : '$' (CamelCaseIdentifier | Identifier);
CamelCaseIdentifier : 'a'..'z' AlphaNum*;
Identifier          : 'A'..'Z' AlphaNum*;

// a fragment rule can't be used inside parser rules, only in lexer rules
fragment AlphaNum   : 'a'..'z' | 'A' .. 'Z' | '0'..'9';

我是编译器和Antlr的初学者,但从我有限的理解来看,大写(lexer)规则只适用于正则表达式。小写(解析器)规则也可以兼作lexer规则(参见[1])。所以变量是大写还是小写并不重要,对吧

不管怎样,我可能错了,但这样做不是更简单吗:

[...]
variable: '$' ('a'..'z' | 'A' .. 'Z') ALPHANUM*;
ALPHANUM: ('a'..'z' | 'A' .. 'Z' | '0'..'9');
[...]
?

如果您计划重用('a'..'z'|'a'..'z'),那么您应该:

[...]
variable: '$' ALPHA ALPHANUM*;
fragment ALPHA: ('a'..'z' | 'A' .. 'Z')
ALPHANUM: (ALPHA | '0'..'9');
[...]
抱歉,如果这是完全不正确的,我仍在学习

[1]