实习日志(1)初识flex & bison (计算器的设计)
来源:互联网 发布:fx2n编程手册 编辑:程序博客网 时间:2024/05/29 09:23
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">我怎么也没想到来公司了竟然是做编译原理相关的工作。 毕竟没有学过编译原理 ,看到正则表达式就晕了。T_T</span>
刚刚拿到flex & bison 这本书的时候 感觉一头雾水,完全知道干什么的。第一天看了词法分析工具flex。直接用flex写出统计单词,行数,字符数的程序,比起直接用C++去模拟,简单的多了。顿时就感觉这个东西好叼。然后就看到了bison 这个这个东西, 后来才懂flex & bison 这2个东西 一个时词法分析,一个时语法分析。2个东西在一起就可以写编译器了。。。。
* wc程序 */%option noyywrap%{int chars = 0;int words =0;int lines = 0;%}%%[a-zA-Z]+{ ++words;chars += strlen(yytext) ;}\n { ++lines ; ++chars;}. { ++chars ; }%%int main(int argc,char* argv[]){yylex();printf("%d %d %d\n",lines,words,chars);return 0;}
虽然写一个计算器其实时很简单的,但是还是整整用了2天才写出一个完成功能的计算器 。。。。
首先是写词法分析分析器 calc1-2.l ,包含了调试的代码
/*calc1-2.l*/%{#define YYSTYPE double#include "calc1-2.tab.h"#include <stdlib.h>#ifdef debug YYSTYPE yylval;#endif%}%%"+" { return ADD; }"-" { return SUB; }"*" { return MUL; }"/" { return DIV; }"|" { return ABS; }"(" { return OP; }")" { return CP; }([0-9]*\.?[0-9]+|[0-9]+\.) { yylval = atof(yytext); return NUMBER;}"sqrt" { return SQRT; }"**" { return SQR; }\n { return EOL; }[ \t] {}"//".* {}%%#ifdef debugint main(int argc ,char* argv[]){ int token; while(token = yylex()) { printf("%d",token); if(token ==NUMBER) { printf("= %f\n",yylval); } else printf("\n"); } return 0;}#endif
然后就是些语法分析器。我想实现的功能比较多,所以刚开始写规则的时候有点乱,后来理清楚了,才运行正确。
语法分析器 calc1-2.y
/* calc1-2.y*/%{#define YYSTYPE double#include<stdio.h>#include<math.h>%}%token NUMBER%token ADD SUB MUL DIV ABS%token EOL%token OP CP%token SQR SQRT%%calclist: | calclist exp EOL { printf("ans = %f\n>>> " ,$2 ); } ;exp: factor { $$ = $1; } | exp ADD factor { $$ = $1 + $3 ; } | exp SUB factor { $$ = $1 - $3 ; } ;factor: tmp { $$ =$1; } | factor MUL tmp { $$ = $1 * $3; } | factor DIV tmp { $$ = $1 / $3; } ;tmp: term { $$ = $1; } | SUB tmp { $$ = -$2; } | tmp SQR tmp { $$ = pow($1,$3); /*printf("%d %d %d\n",$1,$2,$3);*/} ;term: NUMBER { $$ = $1;} | ABS exp ABS { $$ = fabs($2);} | OP exp CP { $$ = $2; } | SQRT OP exp CP { $$ = sqrt($3) ;/*printf(" %d %d %d\n",$1,$2,$3);*/ } ;%%int main(){ printf(">>> "); while(1) yyparse(); return 0;}yyerror(char *s){ fprintf(stderr,"error : %s\n",s);}
关于用yylval传递值得问题,一开始的计算器都整数的,后来想改成浮点数,不知道怎么改。后来在一篇博客上看到了。宏定义 YYSYYPE 的类型成自己想要的类型,一般定义成公用体。 最坑了一点是是 宏定义一定要定义在代码首行,不然一直错误。 我这里卡了好久。 。。
关于编译,看到了makfile这个东西,所以就去看了一点基础的。 用makefile 可以实现自动化编译。
/*makefile*/calc1-2: calc1-2.l calc1-2.y bison -d calc1-2.yflex -o calc1-2.lex.c calc1-2.lcc -o $@ calc1-2.tab.c calc1-2.lex.c -llcalc1-2.lex:calc1-2.y calc1-2.lbison -d calc1-2.yflex -o calc1-2.lex.c calc1-2.lcc -D debug -o $@ calc1-2.lex.c -llclean:rm calc1-2.lex.crm calc1-2.tab.hrm calc1-2.tab.crm calc1-2
编译 calc1-2 没有调试的
➜ calc1-2 make calc1-2bison -d calc1-2.ycalc1-2.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]flex -o calc1-2.lex.c calc1-2.lcc -o calc1-2 calc1-2.tab.c calc1-2.lex.c -llcalc1-2.tab.c:1141:16: warning: implicit declaration of function 'yylex' is invalid in C99 [-Wimplicit-function-declaration] yychar = yylex (); ^calc1-2.tab.c:1354:7: warning: implicit declaration of function 'yyerror' is invalid in C99 [-Wimplicit-function-declaration] yyerror (YY_("syntax error")); ^calc1-2.y:46:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]yyerror(char *s)^calc1-2.y:49:1: warning: control reaches end of non-void function [-Wreturn-type]}^4 warnings generated.
编译带调试功能的calc1-2.lex
➜ calc1-2 make calc1-2.lexbison -d calc1-2.ycalc1-2.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]flex -o calc1-2.lex.c calc1-2.lcc -D debug -o calc1-2.lex calc1-2.lex.c -llcalc1-2.l:32:17: warning: using the result of an assignment as a condition without parentheses [-Wparentheses] while(token = yylex()) ~~~~~~^~~~~~~~~calc1-2.l:32:17: note: place parentheses around the assignment to silence this warning while(token = yylex()) ^ ( )calc1-2.l:32:17: note: use '==' to turn this assignment into an equality comparison while(token = yylex()) ^ ==1 warning generated.
运行calc1-2 测试
➜ calc1-2 ./calc1-2>>> 5/2 + 2ans = 4.500000>>> sqrt(3)**2ans = 3.000000>>> 1+4**0.5 ans = 3.000000>>> ^C
➜ calc1-2 make cleanrm calc1-2.lex.crm calc1-2.tab.hrm calc1-2.tab.crm calc1-2
0 0
- 实习日志(1)初识flex & bison (计算器的设计)
- 创建一门新的编程语言-Flex&Bison教程-(3)-更实用的小计算器
- 编译原理—(从零开始)用flex、bison实现一个简单的计算器
- Flex & Bison 计算器性能
- 实习日志(7):Flex的repeater组件
- 实习日志(8):Flex的TitleWindow控件
- Bison-Flex笔记 (转)
- 用Lex(flex)和yacc(bison)写的简单计算器
- 实习日志(5):Flex页面“跳转”
- 实习日志(9):FLEX页面间传值
- Flex&Bison Tips(2010-08-26)如何改善 flex & bison 在VC下的编辑环境
- 创建一门新的编程语言-Flex&Bison教程-(1)-初探
- 编译原理--计算器Flex+Bison实现
- 使用 flex & bison 生成科学计算器
- 使用flex和bison编写计算器
- Flex和Bison进行语法分析(转载)
- 编译器(汇编器)开发工具Flex和Bison的使用方法之Flex
- 实习日志(4):Flex向Servlet传值
- tableView的基本使用
- PBAS运动目标检测算法
- android--调用系统相机拍照,显示并保存照片 - zhengwen
- 树莓派SD卡制作(Windows下制作Debian镜像)
- Android高效率编码-细节,控件,架包,功能,工具,开源汇总,你想要的这里都有
- 实习日志(1)初识flex & bison (计算器的设计)
- 黑马程序员_java IO流
- 源程序分析
- 实战c++中的vector系列--vector<unique_ptr<>>作为函数的参数
- Xcode7 Http请求
- AdaBoost--从原理到实现
- spring mvc controller间跳转 重定向 传参
- 海量数据处理学习
- poj1703