yacc学习笔记(3) 2014.04.11

实现解析c++ #include 头文件的语法, 暂时没有实现 嵌套解析 #include

codegen.l
% option noyywrap
% option yylineno

% {
#include 
< stdio.h >
#include 
< stdlib.h >
#include 
" codegen.tab.h "
#define  YYDEBUG 0  //  将这个变量设置为1则表示启动Yacc的调试功能

#define  YYERROR_VERBOSE

extern   int  yylex();
extern   void  yyerror( char *  s);

% }

% x _STATE_INCLUDE_
% x _STATE_INCLUDE_FILE_

%%

" # " [ \t] * " include "  { 
        BEGIN _STATE_INCLUDE_;  
//  进入 _STATE_INCLUDE_ 状态
         return  TOKEN_INCLUDE;
    }

< _STATE_INCLUDE_ > [ / " |<]* {
        BEGIN _STATE_INCLUDE_FILE_;  //  进入 _STATE_INCLUDE_FILE_ 状态
         return   * yytext;  //  返回引号或尖括号
    }
    
< _STATE_INCLUDE_FILE_ > [ / " |>] {
         return  TOKEN_INCLUDE_FILE;  //  返回头文件标记
    };
    
/ t / n] ;  //  对于额外的空白不处理
%%
int  main(  int  argc,  char   ** argv )
{
    yyparse();
}
void  yyerror( char   * s)
{
    fprintf(stderr, 
" error: %s\n " , s);
}

codegen.y
% {
#include 
< stdio.h >
#include 
< stdlib.h >
% }

% token TOKEN_INCLUDE 
% token TOKEN_INCLUDE_FILE

%%

program:
    
|  program include_process
    ;

include_process:
    TOKEN_INCLUDE 
' < '  TOKEN_INCLUDE_FILE  ' > '  
    {
        printf(
" include = [%s] \n " , $ 3  );
    }
    
|  TOKEN_INCLUDE  ' /" '  TOKEN_INCLUDE_FILE  ' /" '
    {
        printf(
" include = [%s] \n " , $ 3  );        
    }
    
%%

---------------------------------------------------
2014.04.11
上面的解析是有问题的, 当输入 #include <abc> 时,解析结果为空, 看了下书, 原因是在 返回 TOKEN_INCLUDE_FILE 标记时, 没有对 全局变量 yylval 进行赋值
yylval 是一个int 的类型, 在bison生成的代码, yylval是用 YYSTYPE 定义的,可以通过 %union 修改 YYSTYPE 的定义

修改后的代码如下:
codegen.l
% option noyywrap
% option yylineno

% {
#include 
< stdio.h >
#include 
< stdlib.h >
#include 
" codegen.tab.h "
#define  YYDEBUG 1  //  将这个变量设置为1则表示启动Yacc的调试功能

#define  YYERROR_VERBOSE

extern   int  yylex();
extern   void  yyerror( char *  s);

% }

% x _STATE_INCLUDE_BEGIN_
% x _STATE_INCLUDE_FILE_
% x _STATE_INCLUDE_END_

%%

^ " #include "  { 
        BEGIN _STATE_INCLUDE_BEGIN_;
        
return  TOKEN_INCLUDE;
    }

< _STATE_INCLUDE_BEGIN_ > " < "  {
        BEGIN _STATE_INCLUDE_FILE_;
        
return   ' < ' ;
    }
    
< _STATE_INCLUDE_FILE_ > [ ^ \ " >]+ {
        BEGIN _STATE_INCLUDE_END_;
        yylval.m_lpStr 
=  strdup(yytext);
        
return  TOKEN_INCLUDE_FILE;
    }
    
< _STATE_INCLUDE_END_ > " > "  {
        
return   ' > ' ;
    }

/ t / n] ;  //  对于额外的空白不处理

. { printf(
" other " ); }
%%
int  main(  int  argc,  char   ** argv )
{
    yyparse();
}
void  yyerror( char   * s)
{
    fprintf(stderr, 
" error: %s\n " , s);
}

codegen.y
% {
#include 
< stdio.h >
#include 
< stdlib.h >

% }

% union
{
     
char *  m_lpStr;
}

% token TOKEN_INCLUDE
% token TOKEN_INCLUDE_FILE

%%

program:
    
|  program include_process
    ;

include_process:
    TOKEN_INCLUDE 
' < '  TOKEN_INCLUDE_FILE  ' > '
    {
        printf(
" include = [%s] \n " , yylval.m_lpStr );
        free( yylval.m_lpStr );
    }
    
%%

修改后的问题
1. 输出时多了一个空格 和 换行
2. 实现一个 include 解析, 需要这么多的独占状态么?

你可能感兴趣的:(yacc学习笔记(3) 2014.04.11)