1、打开cygwin,进入home目录,home目录在WINDOWS系统的cygwin安装目录映射为home目录。

2、首先,在home目录中新建文件夹,在文件夹中放置如下内容的test1.l

/*统计字数*/

%{

int chars=0;

int words=0;

int lines=0;

%}

%%

[a-zA-Z]+ {words++;chars+=strlen(yytext);}

\n {chars++;lines++;}

. {chars++;}

%%

main(int argc,char**argv)

{

yylex();

printf("%d%d%d\n",lines,words,chars);

}

然后调用flex生成词法分析器

Administrator@2012-20121224HD /home/flexlinux

$ cd /home

Administrator@2012-20121224HD /home

$ cd flexlinux

Administrator@2012-20121224HD /home/flexlinux

$ flex test1.l

Administrator@2012-20121224HD /home/flexlinux

$

可以看到目录中的lex.yy.c就是刚生成的C源码,可分析词法。

Administrator@2012-20121224HD /home/flexlinux

$ ls

lex.yy.c test1.l

二、flex和bison联合工作

1 、我们开始构造一个计算器程序。

创建flex代码

/*计算器*/

%{

enum yytokentype{

NUMBER=258,

ADD=259,

SUB=260,

MUL=261,

DIV=262,

ABS=263,

EOL=264

};

int yylval;

%}

%%

"+" {return ADD;}

"-" {return SUB;}

"*" {return MUL;}

"/" {return DIV;}

"|" {return ABS;}

[0-9]+ {yylval=atoi(yytext);return NUMBER;}

\n {return EOL;}

[ \t] {/*空白忽略*/}

. {printf("非法字符 %c\n",*yytext);}

%%

main(int argc,char**argv)

{

int tok;

while(tok=yylex()){

printf("%d",tok);

if (tok==NUMBER) printf("=%d\n",yylval);

else printf("\n");

}

}

2、编译

Administrator@2012-20121224HD /home/flexlinux

$ flex test2.l

Administrator@2012-20121224HD /home/flexlinux

$ gcc lex.yy.c -lfl

3、运行

Administrator@2012-20121224HD /home/flexlinux

$ ./a

- 12 66

260

258=12

258=66

264

Administrator@2012-20121224HD /home/flexlinux

$ ./a

/ 56 2 + |32

262

258=56

258=2

259

263

258=32

264

Administrator@2012-20121224HD /home/flexlinux

$

(2)计算器的BISON程序

%{

#include

%}

%token NUMBER

%token ADD SUB MUL DIV ABS

%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;}

;

%%

main(int argc,char **argv){

yyparse();

}

yyerror(char *s)

{

fprintf(stderr,"error:%s\n",s);

}

$ bison -d test2.y

t$ ls

test2.tab.c test2.tab.h test2.y test2.y~

然后,修改刚才的flex文件,将其命名为test21.l

test2.tab.h中包含了记号编号的定义和yylval的定义,因此,将其第一部分的相关定义删除,并改为:

/计算器/

%{

#include "test2.tab.h"

%}

然后删除,其第三部分的main函数。

最后,进行编译。

bison -d test2.y

flex test21.l

gcc test2.tab.c lex.yy.c -lfl

可以测试一下

root@myhaspl:~# ./a.out

12 + 36 * 2

=84

12 / 6 + 2 * 3

=8

(2)扩充计算器

加入对括号和注释的支持,

首先修改flex文件,在第二部分加入更多的词法规则(对于注释直接忽略):

"("   {return LEFTBRACKET;}

")"   {return RIGHTBRACKET;}

"#". /忽略注释*/

然后,修改bison文件,在第二部分加入更多的语法规则:

term:NUMBER {$$=$1;}

|ABS term {$$=$2>=0?$2:-$2;}

|LEFTBRACKET exp RIGHTBRACKET {$$=$2;}

;

我们的注释以“#”表示

测试结果

myhaspl@myhaspl:~/flex_bison/2$ make

bison -d calculator.y

flex calculator.l

gcc calculator.tab.c lex.yy.c -lfl

myhaspl@myhaspl:~/flex_bison/2$ ls

a.out calculator.tab.c calculator.y makefile

calculator.l calculator.tab.h lex.yy.c

myhaspl@myhaspl:~/flex_bison/2$ ./a.out

12-36*10/(1+2+3)#compute

=-48

^C

myhaspl@myhaspl:~/flex_bison/2$

前面都是以键盘输入 的方式进行计算器运算,我们下面以文件方式提供给该解释器进行计算,首先,将flex文件改为(将其中中文去除,然后对于非法字符的出现进行忽略):

%{

#include "calculator.tab.h"

%}

%%

"+" {return ADD;}

"-" {return SUB;}

"" {return MUL;}

"/" {return DIV;}

"|" {return ABS;}

"(" {return LEFTBRACKET;}

")" {return RIGHTBRACKET;}

"#". /comment/

[0-9]+ {yylval=atoi(yytext);return NUMBER;}

\n {return EOL;}

[ \t] /blank/

. /invalid char/

%

接着,改bison文件,加入对文件的读写

%{

#include

%}

%token NUMBER

%token ADD SUB MUL DIV ABS LEFTBRACKET RIGHTBRACKET

%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;}

|LEFTBRACKET exp RIGHTBRACKET {$$=$2;}

;

%%

main(int argc,char **argv){

int i;

if (argc<2){

yyparse();

}

else{

for(i=1;i

{

FILE *f=fopen(argv[i],"r");

if (!f){

perror(argv[i]);

return (1);

}

yyrestart(f);

yyparse();

fclose(f);

}

}

}

yyerror(char *s)

{

fprintf(stderr,"error:%s\n",s);

}

最后 测试一下

root@myhaspl:~/test/3# make

bison -d calculator.y

flex calculator.l

gcc calculator.tab.c lex.yy.c -lfl

root@myhaspl:~/test/3# ./a.out mycpt1.cpt mycpt2.cpt

=158

=-8

root@myhaspl:~/test/3#

其中两个CPT文件内容类似 为:

12*66/(10-5)

我们接着完善这个计算器程序,让算式能显示出来,修改calculator.l

通过加入printf语句,打印词法分析器解析到的字符。比如 :

..................

[0-9]+ {yylval=atoi(yytext);printf("%d",yylval);return NUMBER;}

\n  {return EOL;}

[ \t] /blank/

. /invalid char/

%%

然后编译执行。

root@myhaspl:~/test/4# make

bison -d calculator.y

flex calculator.l

gcc calculator.tab.c lex.yy.c -lfl

root@myhaspl:~/test/4# ./a.out

12+66

12+66=78

^C

root@myhaspl:~/test/4# ./a.out mycpt1.cpt mycpt2.cpt

12*66/(10-5)=158

77/(10+1)-15=-8

接下来加上读取的行号,将结果的显示更加人性化

flex文件要改:

\n  {printf("",yylineno);yylineno++;return EOL;}

然后,bison文件也改:

calclist:/**/

|calclist exp EOL{printf ("the result is:%d\n",$2);}

;

最后 ,编译运行测试一下。

root@myhaspl:~/test/4# make

bison -d calculator.y

flex calculator.l

gcc calculator.tab.c lex.yy.c -lfl

root@myhaspl:~/test/4# ./a.out mycpt1.cpt mycpt2.cpt

1266/(10-5)the result is:158

12/22-8the result is:-8

77(6-2)the result is:308

77/(10+1)-15the result is:-8

root@myhaspl:~/test/4#

linux c编译原理,C指针原理教程之编译原理-小型计算器实现相关推荐

  1. Kali Linux常用服务配置教程DHCP服务原理

    Kali Linux常用服务配置教程DHCP服务原理 动态主机配置协议(Dynamic Host Configuration Protocol,简称DHCP)是一个局域网的网络协议,基于UDP协议工作 ...

  2. C/C++ 跨平台交叉编译、静态库/动态库编译、MinGW、Cygwin、CodeBlocks使用原理及链接参数选项

    0. 引言 UNIX是一个注册商标,是要满足一大堆条件并且支付可观费用才能够被授权使用的一个操作系统.linux是unix的克隆版本,是由其创始人Linus和诸多世界知名的黑客手工打造的一个操作系统. ...

  3. 关于linux内核的wait等待事件和wakeup的核心原理

    关于linux内核的wait等待事件和wakeup的核心原理 上图注意仔细观察. 其实所有的wait_XXX等wait_event.sleep系列函数,都是 1)设置线程状态, 2)调用schedul ...

  4. 微信小游戏开发教程-2D游戏原理讲解

    微信小游戏开发教程-2D游戏原理讲解 原理 为了更加形象的描述,这里先上一张图: 背景 a. 首先,我们看到背景好像是一张无限长的图片在向下移动.实际则不然,这是一张顶部和底部刚好重叠的图片.这是一种 ...

  5. Linux下内存使用率、CPU使用率、以及运行原理-转

    Linux下内存使用率.CPU使用率.以及运行原理 Linux下怎样查看机器配置啊?cpu/内存/硬盘 dmesg 显示开机信息.kernel会将开机信息存储在ring buffer中.您若是开机时来 ...

  6. 重庆SEO优化:网站通过SEO优化会有哪些好处以及【SEO优化】 深度了解蜘蛛spider抓取原理-专业SEO技术教程

    网站通过SEO优化会有哪些好处       SEO优化自产生以来,受到了众多网络推广人员的的欢迎.其实通过SEO进行优化是有很大的好处的.虽然不是很全面但是还是可以提供一定的帮助.接下来就为大家网络就 ...

  7. 单片机测钳形电流表_指针式钳形电流表的测量原理和使用方法

    指针式钳形电流表的测量原理和使用方法 摘要 : 钳形电流表一般可分为磁电式和电磁式两类.其中测量工频交流 电的是磁电式,而电磁式为交.直流两用式.本文主要介绍磁电式钳形电流 表的测量原理和使用方法. ...

  8. 【Java 虚拟机原理】Dalvik 虚拟机 ( 打包 Jar 文件和 Dex 文件 | 反编译 Dex 文件 | 分析 Dex 文件反编译结果 )

    文章目录 前言 一.打包 Jar 文件和 Dex 文件 1.示例代码 2.打包 Jar 文件 3.打包 Dex 文件 二.反编译 Dex 文件 三.分析 Dex 文件 1.Student 类相关信息 ...

  9. linux ndk编译静态库,Android开发教程:NDK编译静态库失败

    Android---NDK编译静态库失败 Android.mk 相关编译文件: include $(CLEAR_VARS) LOCAL_MODULE    := libdvnca LOCAL_SRC_ ...

  10. Linux shell 交互式编程、TCL/TK 和 Expect 编译与安装、expect 编程

    以下文章资源都来源于网络,保留原作者的一切权利: Expect 被用来进行一些需要进行交互是shell 编程的,比如完成ssh 自动登录,就可以使用 expect 编程来实现 1,获取原始的tcl源码 ...

最新文章

  1. scanf可不可以输入浮点型_数据的输入和输出
  2. 如何将catia装配件附材料_在网上买的快餐桌椅如何安装?餐厅快餐桌椅安装顺序与流程知识...
  3. 阿里中间件再获高度肯定,“三位一体”推动技术普惠
  4. 解决360等等浏览器兼容模式解析不兼容代码
  5. 代理的JavaOne 2016观察
  6. C++之对象的动态建立和释放
  7. 多方安全计算(MPC)原理简介
  8. Windows_cmd_命令
  9. 南京服务器修复,南京戴尔服务器数据恢复
  10. Unity 镜像sprite
  11. python实现随机验证码图片生成
  12. 使用 PoseNet 和实时深度学习项目进行姿势检测
  13. 【我的黑名单】优酷的道德水准之低再次突破我的底线,制片王某剽窃19岁少年创意,陌陌科技也不是什么好鸟
  14. 音频处理二:(左右声道分离)
  15. 金蝶迷你版云服务器没有响应,金蝶迷你版连接金蝶云服务器异常
  16. 商业数字营销师资格考试
  17. 聊天机器人(chatbot)终极指南:自然语言处理(NLP)和深度机器学习(Deep Machine Learning)
  18. [渝粤教育] 四川工程职业技术学院 建筑工程测量 参考 资料
  19. Java学到什么程度才可以找到工作?
  20. eclipse更改主题

热门文章

  1. java中过滤流_第十四讲 Java中的字节流和过滤流
  2. Py_FontMaker和GUI_Py_FontMaker制作嵌入式字库工具,支持内部和外部字库,支持LVGL和非LVGL,支持hash查表,支持RLE压缩,支持图标字体和emoji混合消息显示
  3. 常用设计模式-简单工厂
  4. 一边学计算机一边上班累的说说,一个人上班累的说说心情短语
  5. 金融数字化大大拓宽了金融服务的范围,将长尾人群纳入其中
  6. 卡片电脑PINE64初学笔记
  7. SAP中BOM事务清单CS13中的物料数量单位逻辑梳理及格式调整处理实例
  8. vue数据模板文件的下载三种方法
  9. cf——Boats Competition 赛艇
  10. TCP的socket编程中“全双工的字节流”含义的深刻理解