Flex和Bison协同工作(上)

写个demo练练手

我们的第一个同时使用flex和bison的程序将是一个桌面计算器(desk calculator) 。首先,我们编写一个词法分析器,接着我们编写一个语法分析器并把两者接合起来。

为了让事情变得简单,我们的计算器只需要识别整数、基本算术运算符和一元绝对值操作符。
例子:一个简单的flex词法分析器cal.l

%%
"+"	    { printf("PLUS\n"); }
"-"     { printf("MINUS\n”); } 
"*"     { printf("TIMES\n"); }
"/"     { printf("DIVIDE\n"); }
"|"	    { printf("ABS\n"); }
[0-9]+	{ printf("NUMBER %s\n", yytext); }
\n      { printf("NEWLINE\n"); }
[\t]	{ }
.	    { printf("Xue xi zhe wan yi you sha yong %s\n", yytext); }
%%

前5个模式就是操作符本身,用引号引起,而目前的动作仅仅是打印出匹配的内容。引号告诉flex使用引号内文本的原义,而不是把它们解释称正则表达式。
第6个模式匹配一个整数。这种方括号括起的模式[0-9]可以匹配任意一个数字,接着的+这个符号表示匹配一个或者多个前面的项,也就是由一个或者多个数字组成的字符串。相关的动作利用语法分析器每次匹配后所设置的yytext来打印出匹配的字符串。
第7个模式匹配一个换行符,它使用C语言通常使用的序列:\n。
第8个模式用来忽略空白字符。它匹配任意一个空格或者tab(\t),相关的动作无需做任何事情。
最后一个模式用来匹配其他模式所没有匹配的内容。相关的动作打印出恰当的瞎话。

这个程序咱就简简单单来一下子,菜慢慢上,饭慢慢吃。咋运行我就不用说了吧,不会的看一下上一篇文章。

稍微添加一点剂量

作为协同程序的语法分析器:大多数(包含flex词法分析器)的程序使用词法分析器来获取一个记号流,这样可以方便语法分析器的处理。每当程序需要一个记号时,它调用yylex()来读取一小部分输入然后返回相应的记号。每次它返回的时候,它会记住当前处理的位置,并从这个位置开始去处理下一次调用。如果一个模式不能够产生一个用于调用程序且不可以返回的记号时,词法分析器会在这次yylex()调用中继续分析下去。

下面这个例子,包含了两个可以返回记号的模式,一个返回+操作符,另一个返回数字,还包含一个不做任何事情的空白字符的模式,这个模式用来忽略它所匹配的内容。

"+"   { return ADD; }
[0-9] { return NUMBER; }
[ \t] { /* 忽略空白字符*/ }

其实到现在你应该确定一件事情,没错这个返回值就是给语法分析器(bison)用的。要不他俩怎么链接在一起的嘛。

现在我们开始修改上面的那个简单的词法分析器。来,改成我这样!

%{
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("Mystery character %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");
	}
}

我们在一个C语言的enum中定义记号编号。接着我们把yylval(存储记号值)定义为整型,这对于我们第一版的计算器来说已经够用。现在我们就有了一个能够工作的词法分析器,下一篇语法分析器走起。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值