0

私は lex/yacc を初めて使用し、lex/yacc を使用して SQL パーサーを作成しています。ただし、特定の JOIN クエリ (以下にリスト) では、私のパーサーは意図的に「nested_join_statement」ルールではなく「select_statement」ルールにアクセスしています。

このクエリの正しい出力を取得しています: SELECT * FROM sample1 JOIN sample2 ON sample1.C1 = sample2.C4;
(これは「join_statement ルール」に進み、simple_join ルールを満たします)

しかし、私がこのクエリを試しているとき: SELECT * FROM (SELECT * FROM (SELECT * FROM sample1)T8)AS temp1 JOIN (SELECT * FROM (SELECT * FROM sample2)T9)as temp2 ON temp1.C1 = temp2.​​C4;

(これは理想的には「nested_join_statement」に送られるべきですが、代わりに「select statement」ルール内の「SELECT selection FROM LPAREN select_statement2 RPAREN VAR」ルールに送られ、次のエラー メッセージが表示されます: ERROR:syntax error, unexpected AS, VARを期待)

select_statement よりも nested_join_statement を優先していますが、それでもこのエラーが発生します。理由がわかりません。

lex の VAR は [A-Za-z][A-Za-z0-9_#-]* として定義されます

どんな助けでも大歓迎です。私は必死です。

    manipulation_statement: NEWLINE
            | join_statement SEMICOLON
            | nested_join_statement SEMICOLON
            | select_statement SEMICOLON { flag=0;q=0;}
            | join_statement SEMICOLON NEWLINE
            | nested_join_statement SEMICOLON NEWLINE
            | select_statement SEMICOLON NEWLINE { flag=0;q=0;}
            ;
    nested_join_statement: two_nest_select_join { for(x=0;x<q;x++) strcpy(sj[x], ""); i=0;j=0;vardot=0;q=0;flag=0;nest=0;}
            ;
    join_statement: 
            simple_join { for(x=0;x<q;x++) strcpy(sj[x], ""); i=0;j=0;vardot=0;q=0;flag=0;}
            | simple_join_nest_select { for(x=0;x<q;x++) strcpy(sj[x], ""); i=0;j=0;vardot=0;q=0;flag=0;}
           ;
    simple_join: SELECT selection FROM VAR JOIN VAR ON VAR DOTS VAR EQUAL VAR DOTS VAR { printf("inside simple join\n");                                                                
                                                            if(strcmp($4,$8) == 0) join_table($4,$6,sj,q,$10,$14,"","");
                                                            else join_table($4,$6,sj,q,$14,$10,"",""); p=q;}
        ;

    simple_join_nest_select: SELECT selection FROM VAR JOIN LPAREN select_statement RPAREN AS VAR ON VAR DOTS VAR EQUAL VAR DOTS VAR {
                                                   if (strcmp($4,$12) == 0) join_table($4,"_temp_",sj,q,$14,$18,"","");
                                                    else join_table($4,"_temp_",sj,q,$18,$14,"",""); p=q;}
        ;

    two_nest_select_join: SELECT selection FROM LPAREN select_statement RPAREN AS VAR JOIN LPAREN select_statement RPAREN AS VAR ON VAR DOTS VAR EQUAL VAR DOTS VAR {
                                        join_table("temp1","temp2",sj,q,$18,$22,"",""); }
        ;

    select_statement:  SELECT selection FROM VAR WHERE where_clause { select_table($4,s,i,whr_var,whr_val); 
                                                             for(x=0;x<i;x++) strcpy(s[x],"");i=0; strcpy(whr_var,""); strcpy(whr_val,"");j=0;}
            | SELECT selection FROM VAR {   select_table($4,s,i,whr_var,whr_val); 
                                            for(x=0;x<i;x++) strcpy(s[x],"");i=0;j=0;}
            | SELECT selection FROM LPAREN select_statement2 RPAREN VAR { printf("inner tab: %s\n", inner_tab); printf("dep:%d\n", dep+1);
                                                                            for(x=0; x<i;x++) printf("%s\n", col_array[x]);
                                                                            for(y=0; y<j;y++) printf("%d\n", col_count[y]);
                                                                            strcpy(inner_tab,""); nest =1; dep=0;
                                                                            for(x=0; x<i;x++) strcpy(col_array[x], "");
                                                                            for(y=0; y<j;y++) col_count[x] =0;
                                                                            i=0;j=0;k=0;m=0;}
            ;
    select_statement2: SELECT selection2 FROM VAR { dep++; inner_tab=malloc(strlen($4)); strcpy(inner_tab,$4); }
                | select_list
            ;
    select_list: SELECT selection2 FROM LPAREN select_statement2 RPAREN VAR { dep++; }
        ;
    selection2: ASTERISK { col_array[i] = $1; i++; m++; col_count[j] = m; j++; printf("in level:%d value of k:%d\n",j,m); k=0; m=0;}
      | comma_list2 { col_count[j] = m; j++; printf("in level:%d value of k:%d\n",j,m); k=0; m=0;  }
      ;
    comma_list2: VAR { col_array[i] = $1; i++; m++;}
        | comma_list2 COMMA VAR { col_array[i] = $3; i++; m++; 
                                  k=m;}
        ;
    selection: ASTERISK { if(q != 0 || nest == 1) { for(x=0;x<j;x++) col_count[x]=0; i=0; j=0;flag=1;}
                        s[i] = $1; col_array[i] = $1; i++; col_count[j] = i; j++; 
                        if(q == 0) {sj[q] = $1; q++;} printf("in level t:%d value of k:%d\n",j,i); printf("sj2:%s\n",sj[0]);}
      | comma_list { if (flag ==1 ) {col_count[j] = i; j++; printf("in level 2:%d value of k:%d\n",j,i); k=0; m=0; printf("temp:"); 
                                    for(x=0;x<i;x++) printf("%s ",s[x]); } else {col_count[j] = i; j++;} }
      ;
    comma_list: 
        VAR { if(q != 0 || nest == 1) { for(x=0;x<j;x++) col_count[x]=0; i=0; j=0;flag=1;}
                s[i] = $1; col_array[i] = $1; i++; if(q==0) {sj[q] = $1; q++; }}
        | VAR DOTS VAR { strcpy(temp,""); strcat(temp,$1); strcat(temp,$2); strcat(temp,$3); 
            sj[q] = temp;  q++; 
            printf("temps:"); for(x=0;x<q;x++) printf("%s\n",sj[x]);}
        | comma_list COMMA vardot {if (flag == 1) { s[i] = $3; col_array[i] = $3, i++;} else {sj[q] = $3; q++; vardot++;s[i] = $3; col_array[i] = $3, i++;}
                                                                            }
        ;
4

1 に答える 1

2

文法に reduce/reduce の競合があります。selection と selection2 の間、comma_list と comma_list2 の間です。'2' バージョンは文法ファイルで最初に来るため、常にこれらのルールを使用して削減されます。つまり、select_statement と select_statement2 の違いを見ただけでは、関連する 'FROM' トークンを使用すると、間違った動作をする可能性があります。

あなたの例では、 を見た後、SELECT * FROM (SELECT * FROMこの選択を行う必要があります (括弧内のネストされた選択は、two_nest_select_join の選択、または単純な select_statement の select2 のいずれかである可能性があるため)、select2 を選択するため、これをselect_statement、トークンに到達したときに表示されるエラーにつながりASます-その期待VAR

これを修正したい場合は、より多くの先読みを使用するか、文法を変更して削減/削減の競合を取り除く必要があります。

%glr-parserより多くの先読みを使用するには、バイソンのオプションを使用できる場合があります。ここにはあいまいさがないので、明確化コードを追加する必要はありませんが、他の場所にあいまいさがあれば、結果として実行時エラーが発生する可能性があります。

reduce/reduce の競合を取り除くには、重複する selection2 ルールを取り除く必要があります。それらをすべて対応する選択ルールに変更すると、競合がなくなりますが、以前に使用したいくつかの構造を受け入れるようになりました。拒否されSELECT * FROM (SELECT * FROM VAR WHERE where_clause) VARた可能性があります(拒否したい場合など) 。

于 2012-04-25T17:40:53.853 に答える