编译原理 TEST自动机 词法、语法、语义分析代码

代码本身是 孙悦红《编译原理及实践》附录D 语法、语义及代码分析程序

代码有些错误,做出了修改,并在一些地方进行修改增强了健壮性。代码的词法分析部分改为自己所写的代码,因此会有代码风格不一样的地方
加入了赋初值判断,如果使用未赋初值的变量时,会提示警告信息。

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>
#include<iostream>
#include<fstream>
#define maxvartablep 500
using namespace std;

ifstream fin;
ofstream fout1;


int TESTparse();
int program();
int compound_stat();
int statement();
int expression_stat();
int expression();
int bool_expr();
int additive_expr();
int term();
int factor();
int if_stat();
int while_stat();
int for_stat();
int write_stat();
int read_stat();
int declaration_stat();
int declaration_list();
int statement_list();
int compound_stat();
int name_def(char* name);

char token[20], token1[40];//token保存单词符号,token1保存单词值

char Scanout[300], Codeout[300]; //保存词法分析输出文件名

FILE* fp, * fout; //用于指向输入输出文件的指针

int endF;	//读文件结束标志

struct { //定义符号表结构

	char name[8];
	int address;
	int f;
} vartable[maxvartablep]; //改符号表最多容纳maxvartablep个记录

int vartablep = 0, labelp = 0, datap = 0;

int TESTscan();


//----------------------------------------------------------------------------------------------------------------

string RES[7] = { "if","else","for","while","int","read","write" };
int line;

bool isAlpha(char in)	//判断是否为字母
{
	if ((in >= 'a' && in <= 'z') || (in >= 'A' && in <= 'Z'))
		return true;
	return false;
}

bool isDigit(char in)	//判断是否为数字
{
	if (in >= '0' && in <= '9')
		return true;
	return false;
}

bool isSingle(char in)	//判断是否为符号
{
	if (in == '+' || in == '-' || in == '*' || in == '/' || in == '=' || in == '<' || in == '>' || in == '!' || in == '(' || in == ')' || in == '{' || in == '}' || in == ':' || in == ';')
		return true;
	return false;
}

bool isSingle2(char in)//运算符
{
	if (in == '=' || in == '<' || in == '>' || in == '!')
		return true;
	return false;
}

bool isSingel3(char in)//分节符
{
	if (in == '(' || in == ')' || in == '{' || in == '}' || in == ':' || in == ';')
		return true;
	return false;
}

bool isRES(string out)//为保留字
{
	for (int i = 0; i < 7; i++)
	{
		if (out == RES[i])
			return true;
	}
	return false;
}

void outPrint(string out, string state)	//输出
{
	if (state == "ID" && isRES(out))
		state = out;

	//cout << line << "\t" + state + "\t" + out << endl;
	//fout << line << "\t" + state + "\t" + out << endl;
	fout1 << state + " " + out << endl;
}

void outPrintE(string in, int no)	//错误输出
{
	if (no == 0)
	{
		cout << line << "\tERROR: unknown input \t  " + in << endl;
		fout1 << line << "\tERROR: unknown input \t  " + in << endl;
	}
	if (no == 1)
	{
		cout << line << "\tERROR: wrong input ID \t  " + in << endl;
		fout1 << line << "\tERROR: wrong input ID \t  " + in << endl;
	}
	if (no == 2)
	{
		cout << line << "\tERROR: wrong input NUM \t  " + in << endl;
		fout1 << line << "\tERROR: wrong input NUM \t  " + in << endl;
	}
}

void outPrintExp()	//注释输出
{
	char in = fin.get();
	int flag = 0;
	while (in != EOF)
	{
		cout << in;
		//		fout << in;
		if (flag == 1 && in == '/')
		{
			cout << endl;
			//			fout << endl;
			return;
		}
		if (in == '*')
			flag = 1;
		else
			flag = 0;
		in = fin.get();
	}
}

int TESTscan()//词法分析函数

{
	//打开文件
	fin.open("in.txt", ios::in);
	if (!fin)
	{
		cout << "ERROR:there is no in file" << endl;
		return 0;
	}
	fout1.open("lex.txt", ios::out);

	string out = "";
	char in = fin.get();
	int state = 0;
	int flag = 1;
	line = 1;
	while (in != EOF)
	{
		if (in == ' ' || in == '\n' || in == '\t')
		{
			if (in == '\n')
				line++;
			in = fin.get();
			continue;
		}
		switch (state)
		{
		case 0:	//开始状态
			if (isAlpha(in))//第一个字符为字母
			{
				state = 1;
			}
			else if (isDigit(in))//第一个字符为数字
			{
				state = 2;
			}
			else if (isSingel3(in))//分节符
			{
				state = 3;
			}
			else if (isSingle(in))//运算符
			{
				state = 4;
			}
			else	//错误输入
			{
				out = in;
				outPrintE(out, 0);
				in = fin.get();
			}
			break;

		case 1:	//ID输出
			out = in;
			flag = 1;
			while (in != EOF)
			{
				in = fin.get();
				if (!isSingle(in) && in != '\n' && in != ' ')//读取到空格、换行、符号为止
				{
					if (!isAlpha(in) && !isDigit(in))
						flag = 0;	//判断输入是否正确
					out += in;
				}
				else
				{
					if (flag == 0)
						outPrintE(out, 1);
					else			//正确输入
						outPrint(out, "ID");
					state = 0;
					break;
				}
			}
			break;

		case 2:
			out = in;
			flag = 1;
			while (in != EOF)
			{
				in = fin.get();
				if (!isSingle(in) && in != '\n' && in != ' ')
				{
					if (!isDigit(in))
						flag = 0;
					out += in;
				}
				else
				{
					if (flag == 0 || (out.size() > 1 && out[0] == '0'))
						outPrintE(out, 2);	//错误编号为2
					else
						outPrint(out, "NUM");
					state = 0;
					break;
				}
			}
			break;

		case 3:		//分界符
			out = in;
			in = fin.get();
			outPrint(out, out);
			state = 0;
			break;

		case 4:		//操作符
			char in1, in2;
			in1 = in;
			in = fin.get();
			in2 = in;
			if (in2 == '=' && isSingle2(in1))	//是否为双操作符
			{
				out = in1;
				out += in2;
				in = fin.get();
				outPrint(out, out);
			}
			else if ((in1 == '/' && in2 == '*'))	//是否是注释
			{
				cout << in1 << in2;
//				fout1 << in1 << in2;
				outPrintExp();
				in = fin.get();
			}
			else	//为单操作符
			{
				out = in1;
				outPrint(out, out);
			}
			state = 0;
			break;

		default:
			break;
		}
	}

	fin.close();
	fout1.close();


	printf("词法分析成功!\n");

	return 0; //返回主程序
}


//--------------------------------------------------------------------------------------------------------------------
 
//语法、语义分析及代码生成

//插入符号表动作@name-def↓n, t的程序如下:

int name_def(char* name)
{
	int i, es = 0;

	if (vartablep >= maxvartablep) return(21);

	for (i = vartablep - 1; i == 0; i--) //查符号表
	{
		if (strcmp(vartable[i].name, name) == 0) //在符号表中判断是否存在
		{
			es = 22;//22表示变量重复声明
			break;
		}
	}

	if (es > 0) return(es);
	
	strcpy(vartable[vartablep].name, name);	//变量定义

	vartable[vartablep].address = datap;		//数据存放序号跟变量序号相同

	vartable[vartablep].f = 0;	//判定是否赋初值
	
	fprintf(fout, " LOADI %d\n", 0);		//变量默认初值为0
	fprintf(fout, " STO %d\n", vartable[vartablep].address);

	datap++;//分配一个单元,数据区指针加1

	vartablep++;	//变量数加1

	return(es);
}

//查询符号表返回地址

int lookup(char* name, int* paddress)
{
	int i, es = 0;
	for (i = 0; i < vartablep; i++)
	{
		if (strcmp(vartable[i].name, name) == 0)
		{
			*paddress = vartable[i].address;
			return(es);
		}
	}
	es = 23;//变量没有声明
	return(es);
}

//语法、语义分析及代码生成程序

int TESTparse()
{
	int es = 0;

	if ((fp = fopen("lex.txt", "r")) == NULL)
	{
		printf("\n打开%s错误!\n", Scanout);
		es = 10;
		return(es);
	}

	//printf("请输入目标文件名(包括路径):");

	//scanf("%s",Codeout);

	if ((fout = fopen("res.txt", "w")) == NULL)
	{
		printf("\n创建%s错误!\n", "res.txt");
		es = 10;
		return(es);
	}

	if (es == 0) es = program();

	printf("==语法、语义分析及代码生成程序结果==\n");

	switch (es)
	{
	case 0:
		printf("语法、语义分析成功并抽象机汇编生成代码!\n");
		break;

	case 10:
		printf("打开文件 %s失败!\n", Scanout);
		break;

	case 1:
		printf("缺少{!\n");
		break;

	case 2:
		printf("缺少}!\n");
		break;

	case 3:
		printf("缺少标识符!\n");
		break;

	case 4:
		printf("少分号!\n");
		break;

	case 5:
		printf("缺少(!\n");
		break;

	case 6:
		printf("缺少)!\n");
		break;

	case 7:
		printf("缺少操作数!\n");
		break;

	case 21:
		printf("符号表溢出!\n");
		break;

	case 22:
		printf("变量重复定义!\n");
		break;

	case 23:
		printf("变量未声明!\n");
		break;

	case 24:
		printf("语法错误!\n");
		break;

	case 25:
		printf("程序不全或多余!\n");
		break;
	}
	fclose(fp);
	fclose(fout);

	return(es);
}

//program::={<declaraTIon_list><statement_list>}

int program()
{
	int es = 0, i;
	endF = 0;

	fscanf(fp, "%s %s\n", token, token1);

	printf("%s %s\n", token, token1);

	if (strcmp(token, "{"))//判断是否'{'
	{
		es = 1;
		return(es);
	}

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = declaration_list();	//声明序列

	if (es > 0) return(es);

	printf("------符号表------\n");	//打印符号表

	printf("\t名字 \t地址\n");

	for (i = 0; i < vartablep; i++)

		printf("\t%s\t%d\n", vartable[i].name, vartable[i].address);

	es = statement_list();			//语句序列

	if (es > 0) return(es);

	if (strcmp(token, "}"))//判断是否'}'
	{
		es = 2;
		return(es);
	}

	if (endF == 0)		//如果没读到过结尾,代表文件未读完
		es = 25;

	fprintf(fout, " STOP\n");//产生停止指令

	return(es);
}

//<declaration_list>::=

//<declaration_list><declaration_stat>|<declaration_stat>

//改成<declaration_list>::={<declaration_stat>}

int declaration_list()
{
	int es = 0;

	while (strcmp(token, "int") == 0)		//int开头
	{
		es = declaration_stat();

		if (es > 0) return(es);

	}

	return(es);			//声明部分完
}

//<declaration_stat>↓vartablep,datap,codep ->int ID↑n@name-def↓n,t;

int declaration_stat()
{
	int es = 0;

	fscanf(fp, "%s %s\n", &token, &token1);					//判断是不是数据类型
	printf("%s %s\n", token, token1);

	if (strcmp(token, "ID")) return(es = 3); //不是标识符

	es = name_def(token1);//插入符号表						//判断是否在符号表中

	if (es > 0) return(es);

	fscanf(fp, "%s %s\n", &token, &token1);					//判断是不是;
	printf("%s %s\n", token, token1);

	if (strcmp(token, ";")) return(es = 4);

	fscanf(fp, "%s %s\n", &token, &token1);					//读下一个
	printf("%s %s\n", token, token1);

	return(es);


}

//<statement_list>::=<statement_list><statement>|<statement>

//改成<statement_list>::={<statement>}

int statement_list()
{
	int es = 0;

	while (strcmp(token, "}"))		//如果不是} ,}代表statement结束
	{
		es = statement();
		if (es > 0) return(es);
	}

	//-------------------------------------------------------------------------------
	//fscanf(fp, "%s %s\n", &token, &token1);					//读下一个
	if (fscanf(fp, "%s %s\n", &token, &token1) == EOF)
	{
		if (endF == 1)	//第二次出现EOF是出错
			return 25;
		endF++;			//第一次为EOF是因为会多读一次
	}
		
	printf("%s %s\n", token, token1);
	//-------------------------------------------------------------------------------
	return(es);
}

//<statement>::= <if_stat>|<while_stat>|<for_stat>

// |<compound_stat> |<expression_stat>

int statement()
{
	int es = 0;

	if (es == 0 && strcmp(token, "if") == 0) es = if_stat();//<IF语句>

	else if (es == 0 && strcmp(token, "while") == 0) es = while_stat();//<while语句>

	else if (es == 0 && strcmp(token, "for") == 0) es = for_stat();//<for语句>

	//可在此处添加do语句调用

	else if (es == 0 && strcmp(token, "read") == 0) es = read_stat();//<read语句>

	else if (es == 0 && strcmp(token, "write") == 0) es = write_stat();//<write语句>

	else if (es == 0 && strcmp(token, "{") == 0) es = compound_stat();//<复合语句>

//	if (es == 0 && (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0)) es = expression_stat();//<表达式语句>
	//-------------------------------------------------------------------------------
	else if (es == 0 && (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0) || strcmp(token, ";") == 0)
		es = expression_stat();//<表达式语句>
	//-------------------------------------------------------------------------------
	else es = 24;
		
	return(es);
}

//<IF_stat>::= if (<expr>) <statement > [else < statement >]

/*

if (<expression>)@BRF↑label1 <statement > @BR↑label2 @SETlabel↓label1

[ else < statement >] @SETlabel↓label2其中动作符号的含义如下


@BRF↑label1 :输出 BRF label1,

@BR↑label2:输出 BR label2,

@SETlabel↓label1:设置标号label1

@SETlabel↓label2:设置标号label2

*/

int if_stat() 
{
	int es = 0, label1, label2; //if

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	if (strcmp(token, "(")) return(es = 5); //少左括号

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = expression();

	if (es > 0) return(es);

	if (strcmp(token, ")")) return(es = 6); //少右括号

	label1 = labelp++;//用label1记住条件为假时要转向的标号

	fprintf(fout, " BRF LABEL%d\n", label1);//输出假转移指令

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = statement();

	if (es > 0) return(es);

	label2 = labelp++;//用label2记住要转向的标号

	fprintf(fout, " BR LABEL%d\n", label2);//输出无条件转移指令

	fprintf(fout, "LABEL%d:\n", label1);//设置label1记住的标号

	if (strcmp(token, "else") == 0)//else部分处理
	{
		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);

		es = statement();

		if (es > 0) return(es);
	}

	fprintf(fout, "LABEL%d:\n", label2);//设置label2记住的标号

	return(es);
}

//<while_stat>::= while (<expr >) < statement >

//<while_stat>::=while @SET↑labellabel1(<expression>) @BRF↑label2

// <statement >@BR↑label1 @SETlabel↓label2

//动作解释如下:

//@SETlabel↑label1:设置标号label1

//@BRF↑label2 :输出 BRF label2,

//@BR↑label1:输出 BR label1,

//@SETlabel↓label2:设置标号label2

int while_stat()
{
	int es = 0, label1, label2;

	label1 = labelp++;

	fprintf(fout, "LABEL%d:\n", label1);//设置label1标号

	fscanf(fp, "%s %s\n", &token, &token1);

	printf("%s %s\n", token, token1);

	if (strcmp(token, "(")) return(es = 5); //少左括号

	fscanf(fp, "%s %s\n", &token, &token1);

	printf("%s %s\n", token, token1);

	es = expression();

	if (es > 0) return(es);

	if (strcmp(token, ")")) return(es = 6); //少右括号

	label2 = labelp++;

	fprintf(fout, " BRF LABEL%d\n", label2);//输出假转移指令

	fscanf(fp, "%s %s\n", &token, &token1);

	printf("%s %s\n", token, token1);

	es = statement();

	if (es > 0) return(es);

	fprintf(fout, " BR LABEL%d\n", label1);//输出无条件转移指令

	fprintf(fout, "LABEL%d:\n", label2);//设置label2标号

	return(es);
}

//<for_stat>::= for(<expr>,<expr>,<expr>)<statement>

/*

<for_stat>::=for (<expression>;

@SETlabel↓label1< expression >@BRF↑label2@BR↑label3;

@SETlabel↓label4 < expression >@BR↑label1)

@SETlabel↓label3 <语句 >@BR↑label4@SETlabel↓label2

动作解释:

1. @SETlabel↓label1:设置标号label1

2. @BRF↑label2 :输出 BRF label2,

3. @BR↑label3:输出 BR label3,

4. @SETlabel↓label4:设置标号label4

5. @BR↑label1:输出 BR label1,

6. @SETlabel↓label3:设置标号label3

7. @BR↑label4:输出 BR label4,

8. @SETlabel↓label2:设置标号label2

*/

int for_stat()
{
	int es = 0, label1, label2, label3, label4;
	//进入这个函数代表已经匹配了for,读下一个
	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	if (strcmp(token, "(")) return(es = 5);   //少左括号

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = expression();			//条件

	if (es > 0) return(es);

	if (strcmp(token, ";")) return(es = 4); //少分号

	label1 = labelp++;

	fprintf(fout, "LABEL%d:\n", label1);//设置label标号

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = expression();	//第二个表达式
	if (es > 0) return(es);

	label2 = labelp++;
	fprintf(fout, " BRF LABEL%d\n", label2);//输出假条件转移指令

	label3 = labelp++;
	fprintf(fout, " BR LABEL%d\n", label3);//输出无条件转移指令

	if (strcmp(token, ";")) return(es = 4); //少分号

	label4 = labelp++;
	fprintf(fout, "LABEL%d:\n", label4);//设置label4标号

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = expression();
	if (es > 0) return(es);

	fprintf(fout, " BR LABEL%d\n", label1);//输出无条件转移指令

	if (strcmp(token, ")")) return(es = 6); //是否少右括号

	fprintf(fout, "LABEL%d:\n", label3);//设置label3标号

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = statement();					//进入循环体

	if (es > 0) return(es);

	fprintf(fout, " BR LABEL%d\n", label4);//输出无条件转移指令

	fprintf(fout, "LABEL%d:\n", label2);//设置label2标号

	return(es);
}

//<write_stat>::=write <expression>;

//<write_stat>::=write <expression>@OUT;

//动作解释:

//@ OUT:输出 OUT

int write_stat()
{
	int es = 0;

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = expression();

	if (es > 0)return(es);
	if (strcmp(token, ";")) return(es = 4); //少分号

	fprintf(fout, " OUT\n");//输出指令

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	return(es);
}

//<read_stat>::=read ID;

//<read_stat>::=read ID↑n LOOK↓n↑d @IN@STI↓d;

//动作解释:

//@LOOK↓n↑d:查符号表n,给出变量地址d; 没有,变量没定义

//@IN:输出IN

//@STI↓d:输出指令代码STI d

int read_stat()
{
	int es = 0, address;

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	if (strcmp(token, "ID")) return(es = 3); //少标识符

	es = lookup(token1, &address);

	if (es > 0) return(es);

	fprintf(fout, " IN \n");//输入指令

	fprintf(fout, " STO %d\n", address);//指令

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	if (strcmp(token, ";")) return(es = 4); //少分号

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	return(es);
}

//<compound_stat>::={<statement_list>}

int compound_stat()
{ //复合语句函数
	int es = 0;

	fscanf(fp, "%s %s\n", &token, &token1);
	printf("%s %s\n", token, token1);

	es = statement_list();

	return(es);
}

//<expression_stat>::=<expression>;|;

int expression_stat()
{
	int es = 0;
	if (strcmp(token, ";") == 0)
	{
		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);

		return(es);
	}
	es = expression();

	if (es > 0) return(es);

	if (strcmp(token, ";") == 0)
	{
		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);
		return(es);
	}
	else
	{
		es = 4;
		return(es);//少分号
	}
}

//<expression>::=ID↑n@LOOK↓n↑d@ASSIGN=<bool_expr>@STO↓d |<bool_expr>

int expression()	//表达式 < = >等
{
	int es = 0, fileadd;
	char token2[20], token3[40];

	if (strcmp(token, "ID") == 0)
	{
		fileadd = ftell(fp); //@ASSIGN记住当前文件位置

		fscanf(fp, "%s %s\n", &token2, &token3);	//超前读
		printf("%s %s\n", token2, token3);

		if (strcmp(token2, "=") == 0) //'='		赋值语句
		{
			int address;
			es = lookup(token1, &address);			//搜索符号表,看有没有定义
			if (es > 0) return(es);

			fscanf(fp, "%s %s\n", &token, &token1);
			printf("%s %s\n", token, token1);

			es = bool_expr();
			if (es > 0) return(es);

			vartable[address].f = 1;	//变量已经赋值-----------------------------------------

			fprintf(fout, " STO %d\n", address);	//STO D  将操作数栈栈顶单元内容存入内存单元 D,且栈顶单元内容保持不变
		}
		else
		{
			fseek(fp, fileadd, 0); //若非'='则文件指针回到'='前的标识符

			printf("%s %s\n", token, token1);

			es = bool_expr();
			if (es > 0) return(es);
		}		
	}
	else es = bool_expr();

	return(es);
}

//<bool_expr>::=<additive_expr>

// |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >

/*

<bool_expr>::=<additive_expr>

|< additive_expr >><additive_expr>@GT

|< additive_expr ><<additive_expr>@LES

|< additive_expr >>=<additive_expr >@GE

|< additive_expr ><=< additive_expr >@LE

|< additive_expr >==< additive_expr >@EQ

|< additive_expr >!=< additive_expr >@NOTEQ

*/

int bool_expr()
{
	int es = 0;
	es = additive_expr();		//运算符左边
	if (es > 0) return(es);
	if (strcmp(token, ">") == 0 || strcmp(token, ">=") == 0
		|| strcmp(token, "<") == 0 || strcmp(token, "<=") == 0
		|| strcmp(token, "==") == 0 || strcmp(token, "!=") == 0)	//运算符
	{
		char token2[20];
		strcpy(token2, token);//保存运算符

		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);

		es = additive_expr();	//运算符右边

		if (es > 0) return(es);

		//token2 刚才保存的运算符
		if (strcmp(token2, ">") == 0) fprintf(fout, " GT\n");
		if (strcmp(token2, ">=") == 0) fprintf(fout, " GE\n");
		if (strcmp(token2, "<") == 0) fprintf(fout, " LES\n");
		if (strcmp(token2, "<=") == 0) fprintf(fout, " LE\n");
		if (strcmp(token2, "==") == 0) fprintf(fout, " EQ\n");
		if (strcmp(token2, "!=") == 0) fprintf(fout, " NOTEQ\n");

	}
	return(es);
}

//<additive_expr>::=<term>{(+|-)< term >}

//< additive_expr>::=<term>{(+< term >@ADD |-<项>@SUB)}

int additive_expr()		//算式表达式
{
	int es = 0;
	es = term();	//第一个项
	if (es > 0) return(es);
	while (strcmp(token, "+") == 0 || strcmp(token, "-") == 0)	//判断表达式后面还有没有项,没有此时token为; 或其他符号
	{
		char token2[20];
		strcpy(token2, token);
		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);

		es = term();
		if (es > 0) return(es);

		if (strcmp(token2, "+") == 0) fprintf(fout, " ADD\n");
		if (strcmp(token2, "-") == 0) fprintf(fout, " SUB\n");
	}
	return(es);
}

//< term >::=<factor>{(*| \)< factor >}

//< term >::=<factor>{(*< factor >@MULT | \< factor >@DIV)}

int term()							//项
{
	int es = 0;
	es = factor();
	if (es > 0) return(es);
	while (strcmp(token, "*") == 0 || strcmp(token, "/") == 0)	//一个因子后面是不是还有算式
	{

		char token2[20];

		strcpy(token2, token);

		fscanf(fp, "%s %s\n", &token, &token1);

		printf("%s %s\n", token, token1);

		es = factor();

		if (es > 0) return(es);

		if (strcmp(token2, "*") == 0) fprintf(fout, " MULT\n");

		if (strcmp(token2, "/") == 0) fprintf(fout, " DIV\n");
	}
	return(es);
}

//< factor >::=(<additive_expr>)| ID|NUM

//< factor >::=(< expression >)| ID↑n@LOOK↓n↑d@LOAD↓d |NUM↑i@LOADI↓i

int factor()	//因子
{
	int es = 0;
	if (strcmp(token, "(") == 0)
	{
		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);
		es = expression();
		if (es > 0) return(es);
		if (strcmp(token, ")")) return(es = 6); //少右括号
		fscanf(fp, "%s %s\n", &token, &token1);
		printf("%s %s\n", token, token1);
	}
	else
	{
		if (strcmp(token, "ID") == 0)
		{
			int address;

			es = lookup(token1, &address);//查符号表,获取变量地址,判断是否存在

			//-----------------------------------------------------------------------------------------------------
			if (vartable[address].f == 0)
				cout << "警告!未初始化变量" << endl;
			//-----------------------------------------------------------------------------------------------------

			if (es > 0) return(es);//变量没声明

			fprintf(fout, " LOAD %d\n", address);	//LOAD D 将内存单元 address 中的内容加载到操作数栈

			fscanf(fp, "%s %s\n", &token, &token1);
			printf("%s %s\n", token, token1);

			return(es);
		}

		if (strcmp(token, "NUM") == 0)
		{
			fprintf(fout, " LOADI %s\n", token1);		//输出中间代码,LOADI  常量 将常量压入操作数栈
			fscanf(fp, "%s %s\n", &token, &token1);
			printf("%s %s\n", token, token1);
			return(es);
		}
		else
		{
			es = 7;//缺少操作数
			return(es);
		}
	}
	return(es);
}

//主程序

int main() {
	int es = 0;

	TESTscan();//调词法分析

	if (es == 0)
	{
		es = TESTparse(); //调语法、语义分析并生成代码
		if (endF == 0)
			es = 25;
		if (es == 0) printf("语法、语义分析并生成代码成功!\n");
		else printf("语法、语义分析并生成代码错误!\n");
	}
	return 0;
}
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值