《Flex与Bison中文版》填坑之旅_2#

书上面fb1-5.l和fb1-5.y两个案例在本人的环境(请参考前文)下存在错误:

  1. fb1-5.tab.cpp:602:23: error: 'yylex' was not declared in this scope
  2. fb1-5.tab.cpp:1452:35: error: 'yyerror' was not declared in this scope
    (在两个地方出现)

所以,在fb1-5.y中还需要补充相关的代码。主要在.y文件的第一部分需要补充声明
extern int yylex();和 void yyerror(const char* s);

  1. 补充yylex()是因为由.y文件生成的parser代码中有要使用由.l文件生成的scanner中的yylex()函数,如果不声明为extern的,那么当编译parser的时候编译器就会报错,找不到该函数。
  2. 补充yyerror()是因为需要前置声明。我不知道作者的环境下是怎样的,但一般C/C++的函数的编写规矩是要前置声明的。
// fb1-5.y
%{
#include 
extern int yylex();  //补充此处代码
void yyerror(char* s); //补充此处代码
%}
/*declare tokens*/
%token NUMBER
%token ADD SUB MUL DIV ABS OP CP
%token EOL
%%
calclist:
    | calclist exp EOL { printf("= %d\n", $2); }
    ;
exp: factor { $$ = $1; }
    | exp ADD factor { $$ = $1 + $3; }
    | exp SUB factor { $$ = $1 - $3; }
    ;
factor: term { $$ = $1; }
    | factor MUL term { $$ = $1 * $3; }
    | factor DIV term { $$ = $1 / $3; }
    ;
term: NUMBER { $$ = $1; }
    | ABS term { $$ = ($2 >= 0)? $2 : - $2; }
    | OP exp CP { $$ = $2 }
    ;
%%
int main(int argc, char **argv){
    yyparse();
    return 0;
}
void yyerror(const char* s){
    fprintf(stderr, "error: %s\n", s);
}

上面的代码中没有使用文件读入,你如果想通过读取文件,那么可以补充yyin相关代码(请参考前文)。

// fb1-5.l
%{
#include"fb1-5.tab.h"
%}
%option noyywrap
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
"(" { return OP;  }
")" { return CP;  }
[0-9]+  { yylval = atoi(yytext); return NUMBER; }
\n  { return EOL; }
[ \t] { /* ignore the white spaces */ }
.   { printf("Mystery character %c\n", *yytext); }
"//".* { /* ignore comments */ }
%%

本人使用的CodeBlocks环境(请参考前文),在对整个工程进行build处理时,第一次编译会报错,说在编译flex生成的cpp时找不到由.y生成的那个头文件。
请不要着急,再次build一下就好了。
因为,CodeBlocks的build过程(没有自己写makefile)是先win_flex处理.l文件,生成了.flex.cpp,然后接着就编译该生成的.flex.cpp,但由于.l文件中include了由bison处理.y后生成的头文件“fb1-5.tab.h”,但这时win_bison还没有处理.y文件,也就没有生成"fb1-5.tab.h"。既然还不存在,那当然会报找不到的错了。


转载请注明出处,否则不太好哇?

END

你可能感兴趣的:(《Flex与Bison中文版》填坑之旅_2#)