2016-04-23 74 views
0

編輯#1:我認爲問題出在我的.l文件中。我不認爲規則被視爲規則,我不知道如何將規則的終端視爲字符串。Flex和Yacc語法問題

我編譯器類的最後一個項目是爲一個簡單的SQL語法編寫一個.l和一個.y文件。我沒有Flex或Yacc的經驗,所以我寫的所有東西都拼湊在一起。我只對這些文件的工作原理有一個基本的瞭解,所以如果你發現我的問題,你是否也可以解釋文件的那部分應該做什麼?我甚至不確定'%'符號的作用。

基本上,當我嘗試解析某些內容時,某些規則不起作用。有些規則是懸而未決的,而有些則是在他們接受時拒絕。我需要實現以下語法:

start 
    ::= expression 

expression 
    ::= one-relation-expression | two-relation-expression 

one-relation-expression 
    ::= renaming | restriction | projection 

renaming 
    ::= term RENAME attribute AS attribute 

term 
    ::= relation | (expression) 

restriction 
    ::= term WHERE comparison 

projection 
    ::= term | term [ attribute-commalist ] 

attribute-commalist 
    ::= attribute | attribute , attribute-commalist 

two-relation-expression 
    ::= projection binary-operation expression 

binary-operation 
    ::= UNION | INTERSECT | MINUS | TIMES | JOIN | DIVIDEBY 

comparison 
    ::= attribute compare number 

compare 
    ::= < | > | <= | >= | = | <> 

number 
    ::= val | val number 

val 
    ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 

attribute 
    ::= CNO | CITY | CNAME | SNO | PNO | TQTY | 
      SNAME | QUOTA | PNAME | COST | AVQTY | 
      S# | STATUS | P# | COLOR | WEIGHT | QTY 

relation 
    ::= S | P | SP | PRDCT | CUST | ORDERS 

這裏是我的.L文件:

%{ 
#include <stdio.h> 
#include "p5.tab.h" 
%} 
binaryOperation  UINION|INTERSECT|MINUS|TIMES|JOIN|DIVIDEBY 
compare   <|>|<=|>=|=|<> 
attribute  CNO|CITY|CNAME|SNO|PNO|TQTY|SNAME|QUOTA|PNAME|COST|AVQTY|S#|STATUS|P#|COLOR|WEIGHT|QTY 
relation  S|P|SP|PRDCT|CUST|ORDERS 
%% 
[ \t\n]+  ; 
{binaryOperation} return binaryOperation; 
{compare}  return compare; 
[0-9]+   return val; 
{attribute}  return attribute; 
{relation}  return relation; 
"RENAME"  return RENAME; 
"AS"   return AS; 
"WHERE"   return WHERE; 
"("   return '('; 
")"   return ')'; 
"["   return '['; 
"]"   return ']'; 
","   return ','; 
.   {printf("REJECT\n"); 
       exit(0);} 
%% 

這裏是我的.Y文件:

%{ 
#include <stdio.h> 
#include <stdlib.h> 
%} 
%token RENAME attribute AS relation WHERE binaryOperation compare val 
%% 

start: 
    expression   {printf("ACCEPT\n");} 
    ; 

expression: 
    oneRelationExpression 
    | twoRelationExpression 
    ; 

oneRelationExpression: 
    renaming 
    | restriction 
    | projection 
    ; 

renaming: 
    term RENAME attribute AS attribute 
    ; 

term: 
    relation 
    | '(' expression ')' 
    ; 

restriction: 
    term WHERE comparison 
    ; 

projection: 
    term 
    | term '[' attributeCommalist ']' 
    ; 

attributeCommalist: 
    attribute 
    | attribute ',' attributeCommalist 
    ; 

twoRelationExpression: 
    projection binaryOperation expression 
    ; 

comparison: 
    attribute compare number 
    ; 

number: 
    val 
    | val number 
    ; 

%% 

yyerror() { 
    printf("REJECT\n"); 
    exit(0); 
} 

main() { 
    yyparse(); 
} 

yywrap() {} 

這裏是我的makefile:

p5: p5.tab.c lex.yy.c 
    cc -o p5 p5.tab.c lex.yy.c 

p5.tab.c: p5.y 
    bison -d p5.y 

lex.yy.c: p5.l 
    flex p5.l 

此作品:

小號RENAME CNO作爲市

這些不:

小號

S其中CNO = 5

我沒有測試過的一切,但我認爲這些問題存在一個共同的問題。

回答

1

您的語法是正確的,問題是您正在交互式運行。當你調用yyparse()時,它會嘗試讀取所有輸入。由於輸入

小號

之後,可能是要麼重命名或它不會接受。同樣,

S其中CNO = 5

之後,可能是一個或多個數字,所以yyparse不會接受,直到它得到一個EOF或意外的標記。

你想要做什麼是照做here並更改p5.l有這些行:

[ \t]+  ; 
\n   if (yyin==stdin) return 0; 

這樣,當你交互式運行它將採取ENTER鍵輸入結束。

此外,要使用left recursion對數:

number: 
    val 
    | number val 
    ; 
+0

謝謝,它的工作要好得多。但我有幾個問題。 if語句是什麼檢查?我不確定'yyin == stdin'的含義。另外,現在程序在一次接受後退出,如果我想輸入更多命令,該怎麼辦? – Pareod

+0

'yyin == stdin'檢查輸入是否來自標準輸入,我們(可能錯誤地)假設輸入是輸入的。在這種情況下,當用戶輸入時,我們假設它是輸入的結尾。如果你想接受多行,你應該把'yyparse'放在一個循環中。或者,您可能需要';'在一個表達式之後,只能從文件中讀取,或者做一個花哨的[repl像這樣](http://stackoverflow.com/questions/6636808/repl-for-interpreter-using-flex-bison)。 –