2012-10-22 2 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

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를 사용하여 컴파일하려고

/* 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; 
} 
, 나는 오류의 몇 가지를 참조하십시오

,
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 

도와 주시겠습니까? 감사!

업데이트 : 잘못된 기능 유형으로 이미 오류가 수정되었습니다.

+0

C++로 컴파일하지 마십시오. C와 C++은 매우 다른 두 언어입니다. –

답변

4

먼저 명백한 오류를 수정 - caesar.yy의 상단에 선언을 추가 mainyyerror (참고 유형을

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

을 반환 - 나는 또한 침묵에 yyerror 서브의 인수에 const 추가 문자열 리터럴에 대한 경고가 전달됩니다).

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

이제 실제 오류를 볼 수 있습니다 :

당신은 caesar.ll 유사한 사소한 수정이 필요

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

첫 번째 한 - 스캐너가 토큰을 반환하려고 RANGE는 정의되지 않았습니다. 을 caesaer.yy에 추가하여 정의 할 수 있지만 문법에 BSTREAM 또는 USTREAM과 같은 다양한 토큰을 사용하지 않아도 구문 오류가 발생합니다.

이렇게하면 문법 충돌이 발생합니다. 이것들은 실제로는 오류가 아니지만 (경고와 비슷 함)주의를 기울이고 싶습니다. Makefile에있는 bison 명령에 -v 플래그를 추가하면 충돌에 대한 정보가 담긴 caesaer.output 파일이 생성됩니다.

당신이 · 출력 파일에서 볼 수있는 모든 상태를 16 일부터 오는 3 개 충돌,이 모든 3 개 충돌이 exp: exp ADD exp 규칙에서 온 사실을 말하고있다

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) 

. 왼쪽과 오른쪽 모두 재귀적인 규칙을 갖는 것은 항상 모호하지만,이 경우 수정 사항은 명백합니다. 나머지 규칙과 일치하는 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"파일은 필요하지 않습니다 (모든 소스 파일에서 일관되게 사용하는 한). 플렉스는 이미 당신에게'extern "C"yywrap "을 선언 할 것입니다. –

+0

@ChrisDodd 아주 유감입니다. 나는 단지 내 문제에주의를 환기시키고 싶었다. 확인해 주시겠습니까? –

3

http://dinosaur.compilertools.net/flex/flex_19.htmlg++flex을 어떻게 사용하는지 읽으십시오. 여기에서 문제는 C 모드에서 사용하고 있으며 C 렉서를 생성합니다. flex-+ 스위치를 사용하십시오.

+0

감사합니다.'% option C++'을 추가하면 거의 컴파일됩니다. 그러나 '오류 :'yylex '가이 범위에서 선언되지 않았습니다'와 같은 오류가 여전히 있습니다. 문제를 해결하는 방법을 이해할 수 없습니다. 'shift/reduce' 경고는 어떻습니까? 나는이 장난감 언어를 쓰레기로 만들 수 있다고 생각한다. – ghostmansd

+0

링크를 게시 한 문서를 읽을 수 있습니다. –

+1

-1 :'- +'옵션은 bison이 기대하는 인터페이스와 완전히 다른 인터페이스를 가진 C++ 스캐너 클래스를 생성합니다 : C++ 렉서가 클래스를 생성하고 클래스를 어떻게 사용하는지 설명합니다. 당신은 일할 수 있지만, 많은 일을 할 수 있습니다. 플렉스가 옵션없이 생성하는 기본 코드는 C++ 코드로 컴파일하는 것이 완벽합니다. –