C/C++知识点之C指针原理(10)-编译原理-小型计算器实现
小标 2019-02-19 来源 : 阅读 511 评论 0

摘要:本文主要向大家介绍了 C/C++知识点之C指针原理(10)-编译原理-小型计算器实现,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了 C/C++知识点之C指针原理(10)-编译原理-小型计算器实现,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之C指针原理(10)-编译原理-小型计算器实现

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联合工作


本博客所有内容是原创,如果转载请注明来源
//blog.csdn.net/myhaspl/


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 <stdio.h>
%}

%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 <stdio.h>
%}

%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<argc;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)

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程