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