编译原理 实验1《词法分析程序设计与实现》

1、定义目标语言的可用符号表

  1. 关键字:if,else,for,while,do,int,read,write,return
  2. 标识符:①标识符由字母、数字组成;②不能把c语言关键字作为标识符;③标识符对大小写敏感;④首字符只能是字母,不能是数字。
  3. 常数:无符号整数值。
  4. 运算符:+、-、*、/、==、<=、>=、!=、=
  5. 界符:,、;、{、}、(、)

2、定义程序输入输出

  1. 程序输入:依照c语言程序规则输入,以txt文本形式存储;
  2. 程序输出:程序依照 类型 值 的形式每行一个进行输出,例如 int int。

3、代码

(1)头文件 analysis.h

#include<stdio.h>
#include<ctype.h>
#include<string.h>
//下面定义保留字表,为简化程序,使用字符指针数组保存所有保留字
//如果想增加保留字,可继续添加,并修改保留字数目 keywordSum
#define keywordSum 9
char *keyword[keywordSum] = {"if","else","for","while","do","int","read","write","return"};
//下面定义纯单分界符的首字符 
char singleword[50] = "!+-*(){};,:"; 
//下面定义双分界符的首字符
char doubleword[10] = "><=!&|";
extern char Scanin[300], Scanout[300];
//用于接收输人输出文件名,在 test _ main.c 中定义
extern FILE *fin ,*fout; 		//用于指向输入输出文件的指针,在 test _ main.c 中定义
int TESTscan () 				//词法分析函数
{
	char ch , token[40]; 		//ch 为每次读人的字符,token 用于保存识别出的单词
 	int es = 0,j,n; 			//es错误代码,0表示没有错误
	 							//j, n为临时变量,控制组合单词时的下标等
	printf("请输人源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输人词法分析输出文件名(包括路径):");
 	scanf("%s",Scanout); 								
 	if(( fin = fopen(Scanin ,"r")) == NULL)				//判断输人文件名是否正确
 	{
		printf("\n打开词法分析输人文件出错!\n"); 	
 		return (1);										//输人文件出错返回错误代码1
 	}
 	if (( fout = fopen (Scanout ,"w")) == NULL )		//判断输出文件名是否正确
 	{
	 	printf("\n创建词法分析输出文件出错!\n");
 		return(2);										//输出文件出错返回错误代码2
 	}
 	ch = getc(fin);
 	while(ch != EOF)
 	{
 		while(ch == ' '|| ch == '\n' || ch == '\t') ch = getc(fin);
 		if(isalpha(ch))										//如果是字母则组合标识符
		{
			token[0] = ch; j = 1;
			ch = getc(fin);	
			while(isalnum(ch))							//如果是字符数字则组合标识符 
														//如果不是则标识符组合结束 
			{
				token[j++] = ch;						//组合的标识符保存在token中 
				ch = getc(fin);							//都下一个字符 
			}
			token[j] = '\0';							//标识符组合结束 
			
			//查保留字
			n = 0;
			while((n < keywordSum) && strcmp(token,keyword[n])) n++;
			if(n >= keywordSum)							//不是保留字,输出标识符 
				fprintf(fout,"%s\t%s\n","ID",token);	//输出标识符符号
			else										//是保留字,输出保留字 
				fprintf(fout,"%s\t%s\n",token,token);	//输出保留字符号 
		}else if(isdigit(ch))							//数组处理 
		{
			token[0] = ch; j = 1;
			ch = getc(fin);								//读下一个字符 
			while(isdigit(ch))							//如果是数字则组合整数;如果不是则整数组合结束
			{
				token[j++] = ch;						//组合整数保存在token中
				ch = getc(fin);							//都下一个字符	
			}
			token[j] = '\0';							//整数组合结束
			fprintf(fout,"%s\t%s\n","NUM",token);		//输出整数符号 
		}else if(strchr(singleword,ch) > 0)				//单分界符处理 
		{
			token[0] = ch; token[1] = '\0';				
			ch = getc(fin);								//读下一个字符以便识别下一个单词 
			fprintf(fout,"%s\t%s\n",token,token); 		//输出单分界符符号 
		}else if(strchr(doubleword,ch) > 0)				//双分界符处理 
		{
			token[0] = ch;
			ch = getc(fin);								//读下一个字符判断是否为双分界符
			if(ch == '=')								//如果是=,组合双分界符  != == >= <= 
			{
				token[1] = ch; token[2] = '\0';			//组合双分界符结束 
				ch = getc(fin);							//读下一个符号以便识别下一个单词 
			} else if(ch == '&')						//判断是否是&& 
			{
				token[1] = ch; token[2] = '\0';
				ch = getc(fin);
			}
			else if(ch == '|')							//判断是否是|| 
			{
				token[1] = ch; token[2] = '\0';
				ch = getc(fin);
			} else
				token[1] = '\0';
			
			fprintf(fout,"%s\t%s\n",token,token);		//输出单或双分界符 
		}else if(ch == '/')								//注释处理 
		{
			ch = getc(fin);								//读下一个字符 
			if(ch == '*')								//如果是*,则开始处理注释 
			{
				char ch1;
				ch1 = getc(fin);						//读下一个字符 
				do
				{
					ch = ch1; ch1 = getc(fin);			//删除注释 
				} while((ch != '*' || ch1 != '/')&&ch1 != EOF);
														//直到遇到注释结束符 * / 或文件尾 
				ch = getc(fin); 						//读下一个字符以便识别下一个单词 
			}else										//不是*则处理单分界符 
			{
				token[0] = '/'; token[1] = '\0';
				fprintf(fout,"%s\t%s\n",token,token);	//输出单分界符 
			}
		}else											//错误处理 
		{
			token[0] = ch; token[1] = '\0';
			ch = getc(fin);								//读下一个符号以便识别下一个单词 
			es = 3;										//设置错误代码 
			fprintf(fout,"%s\t%s\n","ERROR",token);		//输出错误符号 
		}
	}
	fclose(fin);									//关闭输入输出文件 
	fclose(fout);
	return(es);										//返回主程序 
}

(2)测试 main.cpp

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include"analysis.h"
extern int TESTscan();
char Scanin[300],Scanout[300];			//用于接收输入输出文件名
FILE *fin,*fout;						//用于指向输入输出文件的指针
int main() {
	int es = 0;
	es = TESTscan();
	if(es > 0) 
		printf("词法分析有错,编译停止!");
	else
		printf("词法分析成功!\n"); 
} 

4、测试

(1)输入文件 test.txt

在这里插入图片描述

(2)运行

在这里插入图片描述

(3)输入文件 result.txt

在这里插入图片描述

posted @ 2021-11-14 23:13  WorkHaH  阅读(1145)  评论(0编辑  收藏  举报