2012-10-22 195 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++代码。 –