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

时间:2016-02-09 23:14:13

标签: antlr4

当我用作标识符时,我试图让一些sql关键字被接受为标识符。 Antlr的书p210暗示了这个伎俩:

id : 'if' | 'call' | 'then' | ID ;

我有类似的东西,但它没有工作,我认为这是我的误解。 regular_ident是标识符的解析规则:

regular_ident :  // (1)
        KEYWORD_AS_IDENT
        |
        REGULAR_IDENT
    ;

REGULAR_IDENT是idents的主要lex规则。它大致是这个(在这里简化),并且有效:

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)

如果我将fetch aaa作为输入(' aaa'不是关键字),则会解析:

successfully parsing a normal identifier

但如果我给它fetch sparse它就会失败 - 稀疏'是关键字:

failing to parse with a keyword

也许我愚蠢但我无法理解为什么,因为SPARSEKEYWORD_AS_IDENT的成员。 如果我削减&将(2)中的一些粘贴到(1)中得到这个:

regular_ident :
    FILESTREAM
  | SPARSE
  | NO
  | ACTION
  | PERSISTED
  | FILETABLE_DIRECTORY
        |
    REGULAR_IDENT
    ;

它突然对fetch sparse没问题,因为它现在对待稀疏'作为regular_ident:

enter image description here

但为什么(1)不起作用? 我可以通过内联所有KEYWORD_AS_IDENT来解决这个问题,但我需要知道我错过了什么。

所有建议都表示赞赏。

2 个答案:

答案 0 :(得分:1)

我在我自己的语法中使用你的第二种方法(例如MySQL.g),因为这是让它可靠运行的唯一方法。然而,这仍然是ANTLR3。我使用了hack来改变规则keyword识别的令牌类型,以便它返回IDENTIFIER而不是单个关键字令牌。

答案 1 :(得分:1)

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

  

LASTKEYWORD_AS_IDENT之前声明,所以当词法分析器   遇到'最后',它会生成LAST令牌,而不是a   KEYWORD_AS_IDENT。您的开始规则不接受LAST令牌   有效的输入,因此喊叫。你的语法实际上绝对不会   产生KEYWORD_AS_IDENT令牌,因为另一个有效令牌会   以前匹配。看来你正试图让词法分子做的工作   解析器即处理多个语义替代,但当时   令牌到达解析器已经太晚了......你试过制作吗?   KEYWORD_AS_IDENT解析器规则(小写)而不是词法分析器规则?

所以我对词法分析器的理解是错误的,而且他是正确的,我试图让它来完成解析器的工作。