Lex与Yacc学习(八)之变量和有类型的标记(扩展计算器)

变量和有类型的标记

下一步扩展计算器来处理具有单个字母名字的变量,因为只有26个字母 (目前只关心小写字母),所以我们能在26个条目的数组(称它为vbltable)中存储变量。

为了使得计算器更加有用,也可以扩展它来处理多个表达式(每行一个)和使用浮点值。

具有变量和实值的计算器词法ch3-03.l

%{
	#include "ch3-03.tab.h"
	#include 
	extern double vbltable[26];
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?)	{
		yylval.dval = atof(yytext);
		return NUMBER;
	}
[ \t]	;		/*忽略空白*/
[a-z]	{	yylval.vblno = yytext[0] - 'a';
			return NAME;
		}
"$"		{	return 0; /*输入结束*/ }
\n		|
.		return yytext[0];
%%

具有变量和实值的计算器语法ch3-03.y

%{
	double vbltable[26];
%}

%union {
		double dval;
		int vblno;
	}
%token	 NAME
%token		NUMBER
%left 	'-' '+'
%left	'*'	'/'
%nonassoc 	UMINUS

%type  expression

%%
statement_list: statement '\n'
	|	statement_list statement '\n'
statement:	NAME '=' expression		{vbltable[$1] = $3; }
	|	expression		{ printf("= %g\n", $1); }
	;

expression:	expression '+' expression	{ $$ = $1 + $3; }
	|		expression '-' expression	{ $$ = $1 - $3; }
	|		expression '*' expression   { $$ = $1 * $3; }
	|		expression '/' expression	
						{
							if($3 == 0.0)
								yyerror("divide by zero");
							else
								$$ = $1 / $3;
						}
	|	'-' expression %prec UMINUS {$$ = -$2;}
	|	'(' expression ')'	{$$ = $2; }
	|	NUMBER			{ $$ = $1; }
	|	NAME			{ $$ = vbltable[$1]; }
	;
%%

int main()
{
	yyparse();
	return 0;
}

int yyerror(char *s)
{
	printf("%s\n",s);
	return 0;
}


	

编译运行结果

Lex与Yacc学习(八)之变量和有类型的标记(扩展计算器)_第1张图片

你可能感兴趣的:(lex与Yacc)