yacc文法规则加入字符变量名2

上一篇的字符变量都是一个字母的,这不够用,需要支持单词的变量

首先定义一个结构体,用来存储符号和符号的值(可以实现一个哈希表,会比较快)

ch3hdr.h

#define NSYMS 20

struct symtable{
	char *name;
	double value;
}symtable[NSYMS];

extern struct symtable *symlook(char *s);

ch3hdr.c

#include "ch3hdr.h"
#include <string.h>
struct symtable *symlook(char *s)
{
	struct symtable *iterator = symtable;
	for(; iterator < &symtable[NSYMS]; iterator++){
		if (iterator->name && !strcmp(iterator->name, s)){
			return iterator;
		}
		if (!iterator->name){
			iterator->name = strdup(s);
			return iterator;
		}
	}
	yyerror("too many symbols");
	exit(1);
}

cal.y

%{
#include <stdio.h>
#include "ch3hdr.h"

%}
%union{
	double dval;
	struct symtable *symble;
}
%token PRINT
%token <symble> NAME
%token <dval> NUMBER

%type <dval> expression

%left '+' '-'
%left '*' '/'


%%
paragraph:
	paragraph statement '\n'
	|statement '\n'
	;
statement: 
	PRINT expression		{
								printf("\ntest yacc PRINT expression\n");
								printf("result is %lf", $2);
							}
	|NAME '=' expression 	{
								printf("\ntest yacc = expression\n");
								$1->value = $3;
							}
	;

expression: 
	expression '*' expression 	{
								printf("\ntest yacc expression + expression\n");
								$$ = $1 * $3;
							}
	|expression '/' expression 	{
								printf("\ntest yacc expression + expression\n");
								$$ = $1 / $3;
							}
	|expression '+' expression 	{
								printf("\ntest yacc expression + expression\n");
								$$ = $1 + $3;
							}
	|expression '-' expression 	{
								printf("\ntest yacc expression + expression\n");
								$$ = $1 - $3;
							}
	|NUMBER 				{
								printf("\ntest yacc NUMBER\n");
								$$ = $1;
							} 
	|NAME					{
								$$ = $1->value;
							}
	;

%%

cal.l

%{
#include "y.tab.h"
#include "ch3hdr.h"
#include <math.h>
%}
%%
print {printf("\ntest lex print\n"); return PRINT;}
[0-9]+ |
[0-9]*\.[0-9]+ {printf("\ntest lex NUMBER\n");yylval.dval = atof(yytext);  return NUMBER;}
[ \t] ;
[a-zA-Z][a-zA-Z0-9]*		{
								printf("\ntest lex %s", yytext);
								yylval.symble = symlook(yytext);
								return NAME;
							}
"$"  {return 0;}
\n |
. {printf("\ntest lex %s", yytext); return yytext[0];} 
%%

nosourcesmatoMacBook-Pro:~ nosources$ yacc -d cal.y && lex cal.l && cc -o cal y.tab.c lex.yy.c ch3hdr.c -ly -ll

variablename = 1+2*3-4*4

test lex variablename
test lex =
test lex NUMBER

test yacc NUMBER

test lex +
test lex NUMBER

test yacc NUMBER

test lex *
test lex NUMBER

test yacc NUMBER

test yacc expression + expression

test lex -
test yacc expression + expression

test lex NUMBER

test yacc NUMBER

test lex *
test lex NUMBER

test yacc NUMBER

test yacc expression + expression

test lex 

test yacc expression + expression

test yacc = expression
print variablename

test lex print

test lex variablename
test lex 

test yacc PRINT expression
result is -9.000000

















是pl0的语法分析器,编译原理实验; 用C写的。 /语法分析过程中 /利用词法分析的结果进行分析 /严格按照PL0程序定义来编写 / /<程序> ::= <程序首部> <分程序>. /<程序首部> ::= PROGRAM <标识符>; /<分程序> ::= [<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句部分> /<常量说明部分> ::= CONST <常量定义>{,<常量定义>}; /<常量定义> ::= <标识符>=<无符号整数> /<变量说明部分> ::= VAR <标识符>{,<标识符>}; /<过程说明部分> ::= <过程首部>;<分程序>;【原课件中没有最后的分号,经分析应该有分号】 /<过程首部> ::= PROCEDURE <标识符> /<语句部分> ::= <语句>|<复合语句> /<复合语句> ::= BEGIN <语句>{;<语句>} END【符合语句应该注意的是,END前距离END最近的那条语句一定没有分号,其他语句必须有分号】 /<语句>::= <赋值语句>|<条件语句>|<当型 循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句> /<赋值语句> ::= <标识符>:=<表达式> /<读语句> ::= READ(<标识符>{,<标识符>}) /<写语句> ::= WRITE(<表达式>{,<表达式>}) /<过程调用语句> ::= CALL <标识符>【原课件中有分号,实际不应该有】 /<条件语句> ::= IF <条件> THEN <语句> /<当型循环语句> ::= WHILE <条件> DO <语句> /<因子> ::= <标识符>|<常量>|(<表达式>) /<项> ::= <因子>{<乘法运算符><因子>} /<乘法运算符> ::= *|/ /<表达式> ::= [+|-]<项>{<加法运算符><项>} /<加法运算符> ::= +|- /<条件> ::= <表达式><关系运算符><表达式>|ODD <表达式> /<关系运算符> ::= #|=|>|>=|<|<=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值