2016-02-09 39 views
3

我試圖讓一些sql關鍵字被接受爲標識符,當用作標識符。在ANTLR的書P210表明這一招:嘗試在ANTLR4中使用關鍵字作爲標識符;不工作

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

我有類似的東西,但它不工作,我想這是我的一個誤解。 regular_ident是由此的標識符解析規則:

regular_ident : // (1) 
     KEYWORD_AS_IDENT 
     | 
     REGULAR_IDENT 
    ; 

REGULAR_IDENT爲idents主法的規則。這大致是這樣的(這裏的簡化),以及它的工作原理:

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

也許我是愚蠢的,但我不明白爲什麼,因爲SPARSE是成員KEYWORD_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來修復它,但我需要知道我錯過了什麼。

所有建議表示讚賞。

回答

1

我在自己的語法中使用第二種方法(例如MySQL.g),因爲這是獲得此可靠工作的唯一方法。但這仍然是ANTLR3。而且我使用有點破解來更改由規則keyword識別的令牌類型,以便它返回IDENTIFIER,而不是單個關鍵字令牌。從谷歌組ANTLR的討論從埃裏克Vergnaud

+0

「......只有這樣才能讓這個工作可靠」。好奇。似乎不可能這是一個錯誤,但我會挖掘並嘗試重現最低限度。至於關鍵字hackery,如果語言很糟糕,並且TSQL是,那麼解析只能反映這一點。謝謝 – user3779002

1

回覆:所以當詞法分析器 遭遇「最後」,它會生成一個LAST令牌,而不是一個 KEYWORD_AS_IDENT

LASTKEYWORD_AS_IDENT之前聲明。您的開始規則不會接受LAST令牌作爲 有效輸入,因此大聲呼喊。您的語法實際上不會產生KEYWORD_AS_IDENT令牌,因爲另一個有效令牌 之前會匹配。看來你試圖讓詞法分析器做解析器的工作,即處理多個語義替代,但在時間 令牌到達解析器它爲時已晚......您是否嘗試過製作 KEYWORD_AS_IDENT解析器規則(小寫)而不是一個詞法分析規則?

因此,我對詞法分析器的理解是錯誤的,他正確地試圖讓它做解析器的工作。