Posted on 2014-04-10 09:43
S.l.e!ep.¢% 阅读(1924)
评论(0) 编辑 收藏 引用 所属分类:
yacc
实现解析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 解析, 需要这么多的独占状态么?