尝试在ANTLR4中使用关键字作为标识符;不起作用

尝试在ANTLR4中使用关键字作为标识符;不起作用,antlr4,Antlr4,我正在尝试获取一些sql关键字,当用作标识符时,它们将被接受为标识符。Antlr的第210页书提出了以下技巧: id : 'if' | 'call' | 'then' | ID ; 我也有类似的想法,但不起作用,我想这是我的误解。 regular_ident是标识符的解析规则,因此: regular_ident : // (1) KEYWORD_AS_IDENT | REGULAR_IDENT ; REGULAR_IDENT是IDEN

我正在尝试获取一些sql关键字,当用作标识符时,它们将被接受为标识符。Antlr的第210页书提出了以下技巧:

id : 'if' | 'call' | 'then' | ID ;
我也有类似的想法,但不起作用,我想这是我的误解。
regular_ident
是标识符的解析规则,因此:

regular_ident :  // (1)
        KEYWORD_AS_IDENT
        |
        REGULAR_IDENT
    ;
REGULAR_IDENT
是IDENT的主要法律规则。大致是这样的(这里简化了),它可以工作:

REGULAR_IDENT :
        [a-zA-Z]  ( [a-zA-Z0-9] * )
    ;
KEYWORD_AS_IDENT
是特殊单词的列表,这里有一个摘录:

KEYWORD_AS_IDENT :  // (2)
[...snip...]
  | FILESTREAM
  | SPARSE
  | NO
  | ACTION
  | PERSISTED
  | FILETABLE_DIRECTORY
  | FILETABLE_COLLATE_FILENAME
  | FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME
  | FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME
  | FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME
  | COLUMN_SET
  | ALL_SPARSE_COLUMNS
 ;
如果组件在别处定义:

SPARSE : 'sparse' ;
NO     : 'no'
(etc)
如果我给它
fetchaaa
作为输入('aaa'不是关键字),它将解析:

但是如果我给它
fetch sparse
它会失败-“sparse”是一个关键字:

也许我很傻,但我不明白为什么,
SPARSE
KEYWORD\u as_IDENT
的成员。 如果我将(2)部分剪切并粘贴到(1)中,以获得以下结果:

regular_ident :
    FILESTREAM
  | SPARSE
  | NO
  | ACTION
  | PERSISTED
  | FILETABLE_DIRECTORY
        |
    REGULAR_IDENT
    ;
使用
fetch sparse
突然可以了,因为它现在将“sparse”视为常规标识:

但为什么(1)不起作用? 我可以通过将所有
关键字作为_IDENT
内联来修复它,但我需要知道我缺少了什么


感谢您的所有建议。

我在自己的语法中使用您的第二种方法(例如),因为这是使其可靠工作的唯一方法。然而,这仍然是ANTLR3。我还使用了一种黑客技术来更改规则
关键字
识别的令牌类型,以便它返回标识符,而不是单个关键字令牌。

来自谷歌集团antlr讨论的Eric Vergnaud回复:

LAST
KEYWORD_AS_IDENT
之前声明,因此当lexer 遇到“last”,它会生成
last
标记,而不是
关键字作为标识
。您的开始规则不接受
LAST
令牌作为标记 有效的输入,因此叫喊。你的语法实际上永远不会改变 生成一个
关键字\u AS_IDENT
令牌,因为将生成另一个有效令牌 比赛之前。看来你是想让lexer完成你的工作 解析器处理多个语义选择,但同时 令牌到达解析器,已经太晚了。。。你试过做什么吗 关键字作为语法分析器规则(小写)而不是词法规则


所以我对lexer的理解是错误的,他是正确的,我试图让它完成解析器的工作。

“…让它可靠工作的唯一方法”。好奇。似乎不可能,这是一个错误,但我会挖掘,并尝试复制最低限度。至于关键词hackery,如果语言是肮脏的,而TSQL是肮脏的,那么解析只反映了这一点。谢谢