2012-10-22 196 views
1

我在編譯使用g ++的玩具語言的掃描器和解析器。以下是我使用的每個文件的代碼(如果需要,我可以將其發佈到pastebin或其他任何地方)。flex和bison:g ++編譯錯誤

caesar.ll

/* Simple scanner for a Caesar language */ 
%{ 
#include "caesar.tab.h" 
#include <iostream> 
#include <string> 
int chars = 0; 
int words = 0; 
int lines = 0; 
%} 

/* Define constants */ 
OWS   [" "\t]* 
COMMA   {OWS}","{OWS} 
ID    [A-Za-z_][A-Za-z0-9_]* 
INT   ([0-9]+)|("0x"[A-Ha-h0-9]+) 
FLOAT   [0-9]+"."[0-9]+ 
BSTREAM  b[\'\"].*[\'\"] 
USTREAM  u?[\'\"].*[\'\"] 
ARRAY   {LBRACE}({INT}|{FLOAT})({COMMA}({INT}|{FLOAT})){RBRACE} 
LIST   {LBRACKET}.*({COMMA}.*){RBRACKET} 
RANGE   {LBRACE}{INT}":"{INT}(":"{INT})?{RBRACE} 
ARGS   {ID}({COMMA}{ID})* 
LPARENTHESIS "("{OWS} 
RPARENTHESIS {OWS}")" 
LBRACE   "{"{OWS} 
RBRACE   {OWS}"}" 
LBRACKET  "["{OWS} 
RBRACKET  {OWS}"]" 

%% 
%{ 
/*============================================================================*/ 
/* Define types */ 
/*============================================================================*/ 
%} 
{INT} { 
    cout << "int: " << yytext << endl; 
    yylval = atoi(yytext); 
    return INT; 
} /* int type */ 

{FLOAT} { 
    cout << "float: " << yytext << endl; 
    yylval = atof(yytext); 
    return FLOAT; 
} /* float type */ 

{BSTREAM} { 
    cout << "bstream: " << yytext << endl; 
    return BSTREAM; 
} /* bstream type */ 

{USTREAM} { 
    cout << "ustream: " << yytext << endl; 
    return USTREAM; 
} /* ustream type */ 

%{ 
/*============================================================================*/ 
/* Define operators */ 
/*============================================================================*/ 
%} 
"+" { return ADD; } 
"-" { return SUB; } 
"*" { return MUL; } 
"/" { return DIV; } 
"//" { return FDIV; } 
"|" { return ABS; } 
"\n" { return EOL; } 

%{ 
/*============================================================================*/ 
/* Define statements */ 
/*============================================================================*/ 
%} 
{RANGE} { 
    cout << "range: " << yytext << endl; 
    return RANGE; 
} /* range function */ 

%% 

caesar.yy

/* Simple parser for a Caesar language */ 
%{ 
#include <iostream> 
using namespace std; 
%} 

/* Define built-in types */ 
%token INT FLOAT BSTREAM USTREAM 
%token ADD SUB MUL DIV FDIV ABS 
%token EOL 

%% 

calclist: /* nothing */ 
    | calclist exp EOL { 
     cout << $2 << endl; 
    } 
    | calclist EOL { 
     cout << ">>> "; 
    } 
    ; 

exp: factor 
    | exp ADD exp { $$ = $1 + $3; } 
    | exp SUB factor { $$ = $1 - $3; } 
    | exp ABS factor { $$ = $1 | $3; } 
    ; 

factor: term 
    | factor MUL term { $$ = $1 * $3; } 
    | factor DIV term { $$ = $1/$3; } 
    ; 

term: INT 
    | ABS term { $$ = $2 >= 0? $2 : - $2; } 
    ; 

%% 

main() 
{ 
    cout << ">>> "; 
    yyparse(); 
} 

yyerror(char *error) 
{ 
    cerr << error; 
} 

Makefile

caesar: caesar.ll caesar.yy 
    bison -d caesar.yy 
    flex caesar.ll 
    g++ -o [email protected] caesar.tab.cc lex.yy.c -lfl 

當我嘗試編譯使用make它,我看到幾個錯誤:

bison -d caesar.yy 
caesar.yy: conflicts: 3 shift/reduce 
flex caesar.ll 
g++ -o caesar caesar.tab.cc lex.yy.c -lfl 
caesar.tab.cc: In function 'int yyparse()': 
caesar.tab.cc:1281:16: error: 'yylex' was not declared in this scope 
caesar.tab.cc:1470:35: error: 'yyerror' was not declared in this scope 
caesar.tab.cc:1612:35: error: 'yyerror' was not declared in this scope 
caesar.yy: At global scope: 
caesar.yy:46:20: error: ISO C++ forbids declaration of 'yyerror' with no type [-fpermissive] 
caesar.ll:3:24: fatal error: caesar.tab.h: No such file or directory 
compilation terminated. 
make: *** [caesar] Error 1 

請問您能幫我嗎?謝謝!

UPDATE:我已經修復了不正確的函數類型的錯誤。

+0

甚至不要嘗試將它編譯爲C++。 C和C++是兩種非常不同的語言。 – 2012-10-22 22:12:35

回答

4

首先修復明顯的錯誤 - 添加了聲明caesar.yy的頂部:

int yylex(void); 
void yyerror(const char *); 

和返回類型爲mainyyerror(注意 - 我還添加了const向YYERROR沉默的說法有關傳遞給它的字符串文字警告)。

您需要類似的瑣碎修復了caesar.ll:

#include "caesar.tab.hh" 
using namespace std; 

現在你可以看到真正的錯誤:

caesar.yy: conflicts: 3 shift/reduce 
caesar.ll: In function ‘int yylex()’: 
caesar.ll:79:10: error: ‘RANGE’ was not declared in this scope 

第二個第一 - 掃描儀正在試圖返回一個標記沒有定義的範圍。 您可以將%token RANGE添加到caesaer.yy來定義它,但是您的語法中不會使用它(或其他各種令牌,如BSTREAMUSTREAM),只會導致語法錯誤。

這給我們帶來了語法衝突。這些並不是真正的錯誤(更像是警告),但你確實想要關注它們。在Makefile中向bison命令添加-v標誌,您將得到一個帶有衝突信息的caesaer.output文件。

3間的衝突都來自國家16,您可以在.OUTPUT文件中看到:

state 16 

    5 exp: exp . ADD exp 
    5 | exp ADD exp . 
    6 | exp . SUB factor 
    7 | exp . ABS factor 

    ADD shift, and go to state 10 
    SUB shift, and go to state 11 
    ABS shift, and go to state 12 

    ADD  [reduce using rule 5 (exp)] 
    SUB  [reduce using rule 5 (exp)] 
    ABS  [reduce using rule 5 (exp)] 
    $default reduce using rule 5 (exp) 

這是告訴你,所有3個衝突來自你exp: exp ADD exp規則。有一個左右遞歸的規則總是不明確的,但在這種情況下,修正是顯而易見的 - 將其更改爲exp: exp ADD factor,與其他規則相匹配。

+0

正確!在你進入步驟之前,我已將'extern「C」{int yylex(void);}'添加到'caesar.l'文件和'extern「C」{int yyparse(void); int yylex(void); int yywrap(){return 1; }}到'caesar.y'文件。看起來你有點晚了,但我認爲這是最好的答案。謝謝你這麼好的解釋! – ghostmansd

+0

你不需要'extern「C」'東西,雖然它不會傷害(只要你在所有的源文件中一致)。 flex將已經爲你聲明'extern「C」yywrap「 –

+0

@ChrisDodd我很抱歉發表評論。我只是想提請你注意我的問題。你能檢查嗎? –

3

http://dinosaur.compilertools.net/flex/flex_19.html請閱讀如何使用g++flex。這裏的問題是你在C模式下使用它,它產生了C詞法分析器。使用flex-+開關。

+0

謝謝,它幾乎在添加'%option C++'後編譯。但仍有錯誤,如'錯誤:'yylex'未在此範圍內聲明。無法理解如何解決它們。 'shift/reduce'警告怎麼樣?我想它可以使這個玩具語言成爲垃圾。 – ghostmansd

+0

你可以閱讀我發佈的鏈接文件。它解釋了C++詞法分析器生成的(一個類)以及如何使用其成員函數,如'YYLex'等 –

+1

-1:' - +'選項生成一個C++掃描器類,它具有與野牛期望的完全不同的接口。你可以使它工作,但它很多工作。 Flex不帶任何選項生成的基本代碼非常適合編譯爲C++代碼。 –