使用bison和flex工具[zz]

这里有一个使用bison建立一个简单的计算器的例子:
http://www.cs.berkeley.edu/~maratb/cs164/bison.html

使用bison和flex工具学习编译原理,远比单独看书然后自己编写一些程序生动的多。这样你就不会在那些复杂的字符处理,正则表达式的处理上浪费精力,最后费尽心力,却没有结果,失去了学习的兴趣。

我这里有一个简单的计算器的程序,可以实现加、减、乘、除运算,并支持括号的处理和26个字母作为变量。以前自己使用后缀表达式方式写过一个这样的程序,单单中缀表达式改为后缀表达式就是几百行的代码,反正自己现在还是不知道怎么处理里面复杂的堆栈的(我用了STL的List实现)。



词法处理文件calc.lex内容如下:
%{
/*
* 一个简单计算器的Lex词法文件
*/
#include <stdlib.h>

void yyerror(char*);
#include "calc.tab.h"
%}
%%
/* a-z为变量 */
[a-z] {
yylval = *yytext - 'a';
return VARIABLE;
}
/* 整数 */
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
/* 运算符 */
[-+()=\*\n] {return *yytext;}
/* 空白被忽略 */
[ /t] ;
/* 其他字符都是非法的 */
. yyerror("无效的输入字符");
%%
int yywrap(void)
{
return 1;
}
词法处理的目标就是区分出来每个成员到底是什么,这里有两种 INTEGER和VARIABLE。只要区分出来各个成分词法分析的任务就完成了。



语法处理文件calc.y内容如下:
%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'
%{
#include <stdio.h>
void yyerror(char*);
int yylex(void);
int sym[26];
%}
%%
program:
program statement '\n'
|
;
statement:
expr {printf("%d\n", $1);}
|VARIABLE '=' expr {sym[$1] = $3;}
;
expr:
INTEGER
|VARIABLE{$$ = sym[$1];}
|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;
}
语法分析文件的写法就是将BNF表达式描述一下即可,规则随着条目逐渐细化,变成了可以理解的内容。这里不用管如何实现这些语法的分析,只是需要告知如何构建这些语法。



编译命令如下:
>bison -d calc.y
>flex calc.lex
>gcc calc.tab.c lex.yy.c -o calc

------------------------------------------------

yyparse 是bison生成的函数,用于解析语法,同时yylex是flex生成的函数,用于解析词法,bison生成的函数调用yylex不断处理,处理出来适合的表达式,之后计算.

这里有一个使用bison建立一个简单的计算器的例子:
http://www.cs.berkeley.edu/~maratb/cs164/bison.html

使用bison和flex工具学习编译原理,远比单独看书然后自己编写一些程序生动的多。这样你就不会在那些复杂的字符处理,正则表达式的处理上浪费精力,最后费尽心力,却没有结果,失去了学习的兴趣。

我这里有一个简单的计算器的程序,可以实现加、减、乘、除运算,并支持括号的处理和26个字母作为变量。以前自己使用后缀表达式方式写过一个这样的程序,单单中缀表达式改为后缀表达式就是几百行的代码,反正自己现在还是不知道怎么处理里面复杂的堆栈的(我用了STL的List实现)。



词法处理文件calc.lex内容如下:
%{
/*
* 一个简单计算器的Lex词法文件
*/
#include <stdlib.h>

void yyerror(char*);
#include "calc.tab.h"
%}
%%
/* a-z为变量 */
[a-z] {
yylval = *yytext - 'a';
return VARIABLE;
}
/* 整数 */
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
/* 运算符 */
[-+()=\*\n] {return *yytext;}
/* 空白被忽略 */
[ /t] ;
/* 其他字符都是非法的 */
. yyerror("无效的输入字符");
%%
int yywrap(void)
{
return 1;
}
词法处理的目标就是区分出来每个成员到底是什么,这里有两种 INTEGER和VARIABLE。只要区分出来各个成分词法分析的任务就完成了。



语法处理文件calc.y内容如下:
%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'
%{
#include <stdio.h>
void yyerror(char*);
int yylex(void);
int sym[26];
%}
%%
program:
program statement '\n'
|
;
statement:
expr {printf("%d\n", $1);}
|VARIABLE '=' expr {sym[$1] = $3;}
;
expr:
INTEGER
|VARIABLE{$$ = sym[$1];}
|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;
}
语法分析文件的写法就是将BNF表达式描述一下即可,规则随着条目逐渐细化,变成了可以理解的内容。这里不用管如何实现这些语法的分析,只是需要告知如何构建这些语法。



编译命令如下:
>bison -d calc.y
>flex calc.lex
>gcc calc.tab.c lex.yy.c -o calc

------------------------------------------------

yyparse 是bison生成的函数,用于解析语法,同时yylex是flex生成的函数,用于解析词法,bison生成的函数调用yylex不断处理,处理出来适合的表达式,之后计算.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值