在 Antlr 中处理关键字冲突

Handling Keyword Collision in Antlr

我正在解析一种看起来像这样的语言:

SORT EQUALS,FORMAT=CH

我有 = 定义为

EQUALS          : '=';

如果我这样定义:

EQUALS    : [Ee][Qq][Uu][Aa][Ll][Ss];

我会有名字冲突。

显然,我可以这样做:

ChrEQUALS          : '=';
EQUALS    : [Ee][Qq][Uu][Aa][Ll][Ss];

或者这样: 等于:'='; StrEQUALS : [Ee][Qq][Uu][Aa][Ll][Ss];

但它破坏了与我其他名字的一致性。

有哪些避免冲突但保持一致的好方法?

以下是我考虑过的事情:

1 重命名两者,如果我错误地编码 EQUALS,我将得到一个错误

ChrEQUALS    : '=';
StrEQUALS    : [Ee][Qq][Uu][Aa][Ll][Ss];

2 在所有字符定义前加上 'c'

A​​ntlr 是区分大小写的,所以,

Equals    : '=';
EQUALS    : [Ee][Qq][Uu][Aa][Ll][Ss];

按照惯例,字符文字使用大小写混合命名,字符串全部大写。

或者,也许更精确的命名:

EQUAL     : '=';
EQUALS    : [Ee][Qq][Uu][Aa][Ll][Ss];

如果这只是一次碰撞

我经常在关键词前加上K_来区分。在你的情况下,那看起来像:

EQUALS
 : '='
 ;

K_EQUALS
 : [Ee][Qq][Uu][Aa][Ll][Ss]
 ;

如果您有很多关键字,您可以创建一堆片段来捕获不区分大小写的字母:

EQUALS
 : '='
 ;

K_EQUALS
 : E Q U A L S
 ;

fragment A : [aA];
fragment B : [bB];
...
fragment Z : [zZ];

不仅需要在语法中选择唯一的名称,您还应该考虑目标语言中可能存在的冲突(例如,名为 EOF 的标记肯定会给您在 C 或 C++ 中带来麻烦)。所以目标应该是使名称尽可能唯一(同时仍然保持它们的可读性)。

我通常做的是 append a _SYM or _SYMBOL to all lexer rule names,除了运算符,我用 _OPERATOR 代替。除了那些我有没有这种语义的词法分析器规则(ID,ML_COMMENT,SL_COMMENT 等)。适用于您的情况,您将得到 EQUAL_OPERATOR 和 EQUALS_SYMBOL。如果您有一个关键字 "equal",您仍然可以通过给定的附录很好地分隔运算符和关键字。此外,他们在您的语法中添加了说明。规则如下:

rule1: A EQUAL B;

不完全清楚现在是否有预期的 '=' 或单词 'equal'。通过使用适当的附录,事情会立即变得清晰:

rule1: A EQUAL_OPERATOR B;

如果你有,例如应用程序中定义相同规则(例如 ID)的多个解析器,您甚至可能需要为您的名称添加更多装饰(例如 ID_lang1、ID_lang2 等)。