1

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

例子:

[...]
variable: '$' CamelCaseIdentifier;
CamelCaseIdentifier: ('a'..'z') Identifier*;
Identifier: ('a'..'z' | 'A' .. 'Z' | '0'..'9')+;
[...]

给定输入[...]$a[...]的结果是..., $, a, ...

我正在寻找一种方法来告诉词法分析器,这些规则不应分开:..., $a, ...

谁能帮帮我?

4

3 回答 3

2

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

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

但如果你这样做,输入123456将被标记为Identifier,这可能不是你想要的。此外,该Identifier规则最好命名为AlphaNum。如果你为它制定一个片段规则,你确保词法分析器永远不会AlphaNum在自己身上产生任何标记,而只会将AlphaNum's 用于其他词法分析器规则(如你的CamelCaseIdentifier规则)。如果您还想要与 匹配的规则Identifier,请执行以下操作:

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';
于 2012-06-20T18:22:54.813 回答
0

也许尝试将所有规则名称大写?

编辑:以示例

grammar Dummy;

prog : VARIABLE*;

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


WS: (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN; };
于 2012-06-20T11:59:43.147 回答
0

我是编译器和 Antlr 的初学者,但根据我有限的理解,大写(词法分析器)规则仅适用于正则表达式。小写(解析器)规则也可以兼作词法分析器规则(参见 [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] https://theantlrguy.atlassian.net/wiki/spaces/ANTLR3/pages/2687210/Quick+Starter+on+Parser+Grammars+-+No+Past+Experience+Required

于 2018-01-30T00:57:32.473 回答