【编译原理】Flex/Bison实现计算器 您所在的位置:网站首页 简单的编程代码及其翻译 【编译原理】Flex/Bison实现计算器

【编译原理】Flex/Bison实现计算器

2024-07-12 20:36| 来源: 网络整理| 查看: 265

Flex/Bison实现计算器

文章目录 Flex/Bison实现计算器Flex、Bison介绍源程序结构声明部分翻译规则辅助性C语言例程 使用Dev-C++编译运行使用MinGW在cmd运行源码几个小说明参考文献

Flex、Bison介绍

Flex介绍可以看一看下面这篇,有详细介绍: Flex介绍,使用 Bison 基本上与 Yacc 兼容,并且在 Yacc 之上进行了改进。它经常和 Flex (词法分析器生成器)一起使用。Bison的文件以.y为后缀,生成的文件为 xxx.tab.c和xxx.tab.h

源程序结构

声明部分 %% 翻译规则 %% 辅助性C语言例程

声明部分 %{}%声明 主要包括规则部分的语义过程和过程部分所需的头文件的引用说明、数据定义、全局变量以及函数原型定义等。%声明 对词法单元的声明,eg:%token DIGIT 用户可以使用%left和%right来指明其后面的运算符具有相同的优先级和结合性规则。 翻译规则

→1|2|……|n

另一种写法

: 1 {1} |2 {2} …… |n {n}

eg:

line: expr ‘\n’ {printf("%lf",$1);}

$$表示左部语法变量的属性值,$i表示右边第i个文法符号的值,语义动作是根据$i计算$$的值

辅助性C语言例程 使用Dev-C++编译运行 calc.l %{ #include void yyerror(char*); #include "calc.tab.h" %} %% \.?[0-9]+|[0-9]+\.[0-9]* {yylval=atof(yytext);return INTEGER;} [-+()/*,\n] {return *yytext;} [ \t] ; . yyerror("Error"); %% int yywrap(void) { return 1; } calc.y %token INTEGER %left '+' '-' %left '*' '/' %{ #define YYSTYPE double #include #include #include void yyerror(char*); int yylex(void); %} %% program: program expr '\n' {printf("%lf\n",$2);} | ; expr: INTEGER |expr '+' expr {$$ = $1 + $3;} |expr '-' expr {$$ = $1 - $3;} |expr '*' expr {$$ = $1 * $3;} |expr '/' expr {$$ = $1 / $3;} |'('expr')' {$$ = $2;} ; %% void yyerror(char* s) { fprintf(stderr, "%s\n", s); } int main(void) { printf("A simple calculator:\n"); yyparse(); return 0; } 编译运行

1、在Flex、Bison安装目录下使用cmd。执行:

win_flex -ocalc.c calc.l win_bison -ocalc.tab.h calc.y //注意-o后面没有空格

2、编译calc.c 使用Dev-C++打开calc.c,编译运行就可以了哦。 在这里插入图片描述

使用MinGW在cmd运行 MinGw的安装

MinGw的安装在这里就不一一赘述了,一路next,安装成功后,记得配置环境变量,一定需要配置。

这里的calc.l和calc.y与之前的是一样的。下面是编译运行:

win_flex calc.l win_bison -o calc.tab.h calc.y //注意-o后面有没有空格都可以 gcc -o calc lex.yy.c calc.tab.h //编译 calc //运行calc.exe

在这里插入图片描述

源码 calc.l %{ #include "calc.tab.h" #define YYSTYPE double void yyerror(char*); int yywrap(); %} %% [a-z] {yylval = *yytext - 'a';return VARIABLE;} \.?[0-9]+|[0-9]+\.[0-9]* {yylval = atof(yytext);return INTEGER;} [-+()=/*&|~!^,@\n] {return *yytext;} sin {return SIN;} cos {return COS;} tan {return TAN;} sqrt {return SQRT;} log {return LOG;} pow {return POW;} [ \t] ; . yyerror("error"); %% int yywrap() { return 1; } calc.y %token INTEGER VARIABLE SIN COS TAN POW SQRT LOG %left '+' '-' %left '*' '/' %left '&' %left '|' %left '^' %right '@''~' %left '!' %right UMINUS %{ #include #include #define YYSTYPE double #define pi 3.1415926 void yyerror(char*); int yylex(void); double sym[26]; %} %% program: program statement '\n' | ; statement: expr {printf("%g\n", $1);} |VARIABLE '=' expr {sym[(int)$1] = $3;} ; expr: INTEGER |VARIABLE {$$ = sym[(int)$1];} |expr '+' expr {$$ = $1 + $3;} |expr '-' expr {$$ = $1 - $3;} |expr '*' expr {$$ = $1 * $3;} |expr '/' expr {$$ = $1 / $3;} |expr '&' expr {$$ = (int)$1 & (int)$3;} |expr '|' expr {$$ = (int)$1 | (int)$3;} |'~' expr {$$ = ~(int)$2;} |'@' expr {$$ = sqrt($2);} |expr '@' expr {$$ = $1*sqrt($3);} |expr '!' {int i=1,s=1;for(;iprintf("%lf\n", $1);} | ;

5、输出时整数小数区分,以及小数后面多余0的处理

取整判断小数与整数,取余去掉多余的0 不过通过多次尝试,然后发现C语言提供了简便方法,哈哈哈

如果对你有帮助,点个赞呗。

参考文献

【1】《编译原理》(龙书) 【2】《编译原理》第二版 蒋宗礼、姜守旭



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有