0

我是 lex/yacc 的新手,我正在使用 lex/yacc 编写 SQL 解析器。但是对于特定的 JOIN 查询(​​如下所列),我的解析器故意访问“select_statement”规则而不是“nested_join_statement”规则。

我得到了这个查询的正确输出:SELECT * FROM sample1 JOIN sample2 ON sample1.C1 = sample2.C4;
(这将进入'join_statement rule',满足其中的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”规则,我收到以下错误消息:错误:语法错误,意外 AS,期待 VAR)

我将 nested_join_statement 的优先级置于 select_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

您的语法中存在减少/减少冲突——在 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

如果你想解决这个问题,你需要使用更多的前瞻,或者改变语法来摆脱减少/减少冲突。

要使用更多前瞻,您可以使用 bison 的%glr-parser选项。由于此处没有歧义,因此无需添加任何额外的消歧代码,但如果您在其他地方有歧义,则可能会因此出现运行时错误。

要摆脱减少/减少冲突,您需要摆脱重复的 selection2 规则——如果您将它们全部更改为相应的选择规则,您就摆脱了冲突,但是您现在接受了一些以前的构造会被拒绝(例如SELECT * FROM (SELECT * FROM VAR WHERE where_clause) VAR您可能想要禁止的。

于 2012-04-25T17:40:53.853 回答