用flex与bison配合实现类似c编译器中的include功能遇到难题?

jiang_jixuan 2007-05-22 04:33:30
如题。
大虾们,我在用flex与bison配合实现一个小型编译器的时候,需要类似于c中的#include的功能,我是应该用多编扫描呢?还是可以用一遍扫描就能完成呢?
如果用一编扫描那我需要注意哪些问题呢?
...全文
1108 23 打赏 收藏 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
laomai 2007-11-06
  • 打赏
  • 举报
回复
不错,进来学习。
dai_weitao 2007-05-23
  • 打赏
  • 举报
回复
高深问题,帮顶一下吧
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
freshui(五月的风 - 唉 真饼啊! 多学习,少灌水打游戏)
也许c语言的include .c不是我想表达的意思
我的意思和java的import有点像,java中没有.c和.h的区别,直接就import了一个实现。
我在bison中看到了有叫pure parser的东西,我在想是否可以用这个来实现?
还是刚才那个a.c,b.c
./fbcc ./b.c
用bison 先parse b.c,将 include语句作为一个.yy的一条产生式,遇到的时候就调用flex中的switch_to_buffer,并且重入一次bison的parser,开始对a.c进行编译,a.c编译完成后就回到了b.c include的那一点,然后再继续编译b.c。我就是不知道这个能否完成我所需要的功能,以及我理解是否正确。
freshui 2007-05-23
  • 打赏
  • 举报
回复
哪是不可能的
看来你还没有理解include的意思

include只是把代码在当前位置展开, 就相当于把a.c的代码复制到b.c中include的位置
, 这样的话, 你要a.o有什么用? b.o中已经包含了a.o中相应的函数和变量了

你要生成两个a.o和b.o, 这不是include要做的事情啊~!

一般谁编程序不会inlcude .c文件的, 这个有悖常理

你现在要做的是多文档编译, 不是实现include预处理的功能
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
freshui(五月的风)
老兄,可能我的例子说的有偏颇,我理解需要用一个link的链接器来完成.o的连接。
我现在的重点在于若存在a.c; b.c ,在b.c 中include "a.c"。我在编译b.c的时候自动编译a.c生成一个a.o和b.o,最好是一遍扫描,这个和include有关吧!
比如我实现了 编译器叫fbcc.exe 我只执行
./fbcc ./b.c
我只需要生成.o不需要连接!
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
+----------------+ call+------+
|xx.yy.c::parser |<----|client|
+----------------+.....+------+
|
|auto call
|
V
+----------------+
|xx.ll.c::flex |
+----------------+
auto/call \
+----+ +----+
| a.c| | b.c|
+----+ +----+
freshui 2007-05-23
  • 打赏
  • 举报
回复
那是多文档编译 和include没有关系
这样的话你还要实现一个link的链接器, 不仅仅是用flex bison做编译器了

一个.c文件要编译一下, include不行
如果你开发出了的编译器叫fbcc.exe
那么你编译的时候就要: ./fbcc ./a.c ./b.c
这个要根据输入参数来判断具体操作, 不是include该干的事了
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
+----------------+ call+------+
|xx.yy.c::parser |<----|client|
+----------------+ +------+
|
|auto call
|
V
+----------------+
|xx.ll.c::flex |
+----------------+
/ \
/ \
- '
+----+ +----+
| a.c| | b.c|
+----+ +----+
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
sorry,这个图被搞乱了
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
freshui(五月的风)
我理解你的意思,include只是对文件的展开。
我的意思是说include .c的时候不但展开了定义还展开了实现。
include .h的时候可以只引入符号,但是include .c的时候还引入了实现
我的程序是这样的结构

+----------+ call +----------------+
|client |------->|xx.yy.c::parser |
+----------+ +----------------+
|
|auto call
|
V
+----------------+
|xx.ll.c::flex |
+----------------+
/ \
分别编译 / \ 分别编译
- '
+------------+ +---------------+
| a.c | | b.c |
+------------+ +---------------+
就像我上面说的a.c; b.c ,在b.c 中include "a.c"。我的a.c会被编译一次,b.c会被编译一次。当a.c被编译的时候会产生一个a.o,b.c被编译的时候会产生一个b.o。如果按照你的方法在生成的b.o中就存在a.o的重复的全部实现。
如何去避免在b.o中存在重复的a.o的信息是我关注的要点!
yjdlut 2007-05-23
  • 打赏
  • 举报
回复
好复杂呀,不懂,学习。
freshui 2007-05-23
  • 打赏
  • 举报
回复
一样合适
在bison看来, 只不过include的文件在include的位置展开了
这也是include这个预处理器的功能
如果不是这个功能, 那就不要用include

不管.c和.h还是其它什么东西, 都一样~!
你还没有理解include这个预编译器的功能~!
他是预编译器指令, 你要他做编译期的事情, 是不可能的~!
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
freshui(五月的风)
我理解你的意思了,你是说在bison中根本就不知道有include这回事,bison只是负责一路解析,而flex则将include的文件直接扩展成了一个持续输入的流,因此从bison看来输入流并没有改变!
我相信这个针对类似于c语言中的.h文件的include是完全适合的。

但是如果遇到include 是一个 .c 文件却不一定合适吧。比如 有a.c; b.c ,在b.c 中include "a.c"。这样a.c就会在b.c中被编译一次,而且作为b.c编译结果的一部分存在,而不会单独作为a.c的编译结果存在。

这个你是怎么解决的呢?
jiang_jixuan 2007-05-23
  • 打赏
  • 举报
回复
感谢dai_weitao(疯狂Linux C++)支持
freshui 2007-05-22
  • 打赏
  • 举报
回复
影响就是bision中的yywrap
呵呵, 在执行include的文件尾的时候要return 1, 表示当前buffer执行完毕了,可以接着下一个buffer了

如果return 0的话又从当前buffer的开始解析了, lex就没有办法截获<<EOF>>

jiang_jixuan 2007-05-22
  • 打赏
  • 举报
回复
非常感谢热心的freshui(五月的风) ,
有个问题请教,在flex中include了一个文件,那么会对bison的解析产生影响吧?
那如果说flex中切换了输入流了,bison是不是应该重入一次parser呢?
jiang_jixuan 2007-05-22
  • 打赏
  • 举报
回复
感谢freshui(五月的风) :
但是yywrap return 1表示了扫描的结束阿老大,这个例子我没有看到
你的意思是不是说我在扫描到include的时候不用立刻switch_to_buffer,而等到一个文件扫描完成了过后再扫描另外的文件么?
freshui 2007-05-22
  • 打赏
  • 举报
回复
晕~

#INCLUDE BEGIN(incl);
<incl>[ \t]* {/* eat the whitespace*/ }
<incl>[^ \t\n]+ { // got the include file name
if (TOK_PRINT) printf("[SYSTEM]: >>> Went into %s\n",yytext);
if (TOK_PRINT) printf("[SYSTEM]: >>> Include Stack level:%d\n",include_stack_ptr);

if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf(stderr,"### Fatal Error! Includes nested too deeply!\n Maybe you got the file include itself and loop forever!\n>>Exit...\n");
exit(-1);
}
else
{
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;

yyin = fopen( yytext, "r" );

if ( ! yyin )
{
fprintf(stderr,"### Fatal error! ### \nCan not open included file \"%s\"! \n>>Exit...\n", yytext);
exit(-1);
}
else
{
if (TOK_PRINT) printf(" >>> open file %s!\n", yytext);
}

yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );

BEGIN(INITIAL);
}
}
<<EOF>> {// end of file
if (include_stack_ptr )
{
srcLineNum--;
if(pre_process) popFileName();// pop filename, for tracking src file line stuff

if (TOK_PRINT) printf("[SYSTEM]: <<< EOF of Include file, Current Level:%d\n" ,include_stack_ptr);
if ( --include_stack_ptr < 0 )
{
yyterminate();
}

else
{
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(include_stack[include_stack_ptr] );
if (TOK_PRINT) printf("[SYSTEM]: <<< Out Include file\n");
}
}
else
yyterminate();

}
freshui 2007-05-22
  • 打赏
  • 举报
回复
给你一个我写的例子吧,
include我在lex中处理的, 基本上就不用在bision中操作了, 出了一个文件结尾的时候include_stack_ptr> 0情况下不能return 0 外


#INCLUDE BEGIN(incl);
<incl>[ \t]* {/* eat the whitespace*/ }
<incl>[^ \t\n]+ { // got the include file name
if (TOK_PRINT) printf("[SYSTEM]: >>> Went into %s\n",yytext);
if (TOK_PRINT) printf("[SYSTEM]: >>> Include Stack level:%d\n",include_stack_ptr);

if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf(stderr,"### Fatal Error! Includes nested too deeply!\n Maybe you got the file include itself and loop forever!\n>>Exit...\n");
exit(-1);
}
else
{
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;

yyin = fopen( yytext, "r" );

if ( ! yyin )
{
fprintf(stderr,"### Fatal error! ### \nCan not open included file \"%s\"! \n>>Exit...\n", yytext);
exit(-1);
}
else
{
if (TOK_PRINT) printf(" >>> open file %s!\n", yytext);

}

yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );

BEGIN(INITIAL);
}
}
<<EOF>> {// end of file
if (include_stack_ptr )
{
srcLineNum--;
if(pre_process) popFileName();// pop filename, for tracking src file line stuff

if (TOK_PRINT) printf("[SYSTEM]: <<< EOF of Include file, Current Level:%d\n" ,include_stack_ptr);
if ( --include_stack_ptr < 0 )
{
yyterminate();
}

else
{
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(include_stack[include_stack_ptr] );
if (TOK_PRINT) printf("[SYSTEM]: <<< Out Include file\n");
}
}
else
yyterminate();

}

. { yylval.val = yytext[0]; return T_BADTOKEN; }
freshui 2007-05-22
  • 打赏
  • 举报
回复
根据flex中的例子
在yywrap函数的开头:

if(include_stack_ptr> 0)
return 1;
加载更多回复(3)

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧