创建一门新的编程语言-Flex&Bison教程-(2)-加减乘除
上一篇基本介绍了一些知识,那么现在我们就尝试做一个简单的计算器 首先先写bison文件 test2yy.y %{ #include <iostream> using namespace std; int yylex(); //只是一个声明 int yyerror(const char *); //必须要有 %} %token <dv> Number %type <dv> exp %union { double dv; } %left '+' '-' %left '*' '/' %% main : main exp 'n' { cout << "Result : " << $2 << endl; } | ; exp : exp '+' exp { $$ = $1 + $3 } | exp '-' exp { $$ = $1 - $3 } | exp '*' exp { $$ = $1 * $3 } | exp '/' exp { $$ = $1 / $3 } | '(' exp ')' { $$ = $2 } | Number { $$ = $1 } ; %% int yyerror(const char *emseg) { cout << "Error: " << emseg << endl; } int main() { yyparse(); } 在这里我们需要关注一些事情 bison默认第一个表达式(文中的main)为默认表达式,意思是程序执行时处理的表达式,而其他的(文中的exp)则作为辅助,所以你不必一定要命名它为main %left的作用是规定左优先,因为加减乘除中的乘除需要先运算,在有多个%left的情况下,越下优先级越高 什么意思?假如有 .... %left 'a' 'b' %left 'c' %left 'd' ....那么当遇到这串东西的时候: a c b d 首先d被处理,然后是c,a和b优先级相同,按先后处理 那么,既然有左优先,那就肯定还有右优先 %right 右优先怎么用呢?看这两个例子: 5+2*4-1/3 a = b = c = d 上面的是一个算式,算式是要从左到右算的,因此是左优先 下面是一个赋值语句,需要从右边赋值到左边,那么我们就可以 %right '=' 继续看,我们又发现了$$这个新变量,它代表的是当前表达式的值,所以我们要告诉bison这个表达式的类型是什么,于是便有了上面的%type <dv> exp 实际上 %token <dv> Number 与 %token Number %type <dv> Number 等价 好了,让我们来看新的flex文件 test2ll.l %{ #include <iostream> #include "test2yy.h" //由bison生成 extern int yyerror(const char *); using namespace std; %} %% [0-9]+ { yylval.dv = strtod(yytext,0); return Number; } //无小数点 [0-9]+.[0-9]+ { yylval.dv = strtod(yytext,0); return Number; } //有小数点 [)(+*-/n] { return *yytext; } //直接返回字符为符号 [ t] ; //忽略空格 %% int yywrap() { return 1; } 这里和上一篇比没有什么差别,就不说了 bison -d -otest2yy.c test2yy.y flex -otest2ll.c test2ll.l g++ test2*.c -otest2 ./test2 随便输入点算式,是不是成功了? (2)-加减乘除 结束 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |