簡體   English   中英

解決 SQLite 語法中的解析沖突

[英]Solving a parsing conflict in SQLite grammar

我試圖在某一點擴展 SQLite 的 SQL 語言(文件 parse.y)。 我有一個解析沖突,但是檸檬解析器除了隨機的“1 解析沖突”之外沒有顯示任何內容。 錯誤信息。

問題出在 create_table 可以簡化為“CREATE”或“CREATE OR REPLACE”的位置,然后是 temp,也可以簡化為空令牌。

cmd ::= create_table create_table_args table_properties_args.
create_table ::= createorreplace(C) temp(T) TABLE ifnotexists(E) nm(X) dbnm(Y). {
  // ...
}

%type createorreplace {int}
createorreplace(A) ::= CREATE.  {disableLookaside(pParse); A = 0;}
createorreplace(A) ::= CREATE OR REPLACE.  {disableLookaside(pParse); A = 1;}

%type temp {int}
temp(A) ::= TEMP.  {A = pParse->db->init.busy==0;}
temp(A) ::= .      {A = 0;}

我怎樣才能使“OR REPLACE”可選地減少,同時保留它可以跟隨 TEMP?

由於我只能猜測您可能如何以及在何處更改了 SQLite 的 SQL 語法,因此這個答案必然有些試探性。 但無論如何它可能是有用的。

原始 SQL 語法包含以下產生式(我省略了這些操作,因為它們與診斷沖突無關):

cmd          ::= create_table create_table_args.
create_table ::= createkw temp(T) TABLE
                 ifnotexists(E) nm(Y) dbnm(Z).
createkw(A)  ::= CREATE(A).
temp(A)      ::= TEMP.
temp(A)      ::= .
cmd          ::= createkw(X) temp(T) VIEW
                 ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C) AS select(S).

您似乎已將create_table修改為改為:

create_table ::= createorreplace(C) temp(T) TABLE
                 ifnotexists(E) nm(X) dbnm(Y).
createorreplace(A) ::= CREATE.
createorreplace(A) ::= CREATE OR REPLACE.

這種變化確實會產生沖突,但它與temp可以為空無關。 事實上,它與非終端temp幾乎沒有關系。 您可以將temp替換為TEMP (從而使其成為強制性而不是可選的),並且您仍然會遇到 shift-reduce 沖突。

開始CREATE TEMP的輸入會發生沖突。 該輸入可能是開始

  • CREATE TEMP TABLE ...
  • CREATE TEMP VIEW ...這些顯然是不同的語法,並且沒有歧義

但是當終端CREATE剛剛被讀取並且終端TEMP是前瞻令牌時,這兩種可能性仍然可用。 這不一定是問題。 自下而上的解析器不需要解析將使用哪個可能的生產,直到它到達生產的末尾。 所以原始語法工作正常,沒有沖突。

但請注意,原始語法沒有以終端CREATE開頭的cmd產生。 它有幾個以非終端createkw開頭的cmd產品。 但是那里也沒有混淆的可能性。 終端CREATE在兩個cmd產品(以及我未列出的其他cmd產品,它們也以createkw )中都簡化為createkw

但是,在您修改后的語法中,這兩個產生式並非都以createkw 其中一個已更改為以createorreplace

不包含可選關鍵字TEMP的輸入仍然可以毫無問題地解析。 如果TEMP不存在,則前瞻標記將是create_table命令中的TABLE ,而前瞻標記將是 create view 命令中的VIEW 由於前瞻標記不同,解析器可以毫不費力地決定是歸createkw還是歸createorreplace 類似地,如果輸入實際上是CREATE OR REPLACE ... ,則前瞻標記將是OR ,這明確地強制減少到createorreplace

但如上所示,有問題的輸入會啟動CREATE TEMP 現在,解析器必須在沒有看到終端TEMP之后的任何內容的情況下決定是將CREATE簡化為createkw還是將其簡化為createorreplace 由於無法做出該確定,因此報告了沖突。 (通過查看 Lemon 報告文件parse.out ,您會發現有關該沖突的更多信息。)

解決方案(如果我對您的語法修改的猜測是正確的)是避免強迫解析器做出不必要的決定。 這需要一點語法重復:

cmd          ::= create_table create_table_args.
create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z).
create_table ::= createorreplace temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z).
createkw(A)  ::= CREATE(A).
createorreplace(A) ::= CREATE OR REPLACE.
temp(A)      ::= TEMP.
temp(A)      ::= .
cmd          ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z)
                 eidlist_opt(C) AS select(S).

現在,不跟隨OR REPLACE的終端CREATE始終簡化為createkw ,而序列CREATE OR REPLACE始終簡化為createorreplace 這是有效的,因為除了CREATE OR REPLACE之外,沒有可能解析開始CREATE ORcmd

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM