在 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'
Antlr 是区分大小写的,所以,
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 等)。
我正在解析一种看起来像这样的语言:
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'
Antlr 是区分大小写的,所以,
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 等)。