编译原理:源程序的预处理及词法分析程序的设计与实现(含代码)

源程序的预处理及词法分析程序的设计与实现

写在最前面:代码按着自己的想法写的,与这个博客讲的方法有不一样的地方。
另:我的代码是从文档中读取需要处理的代码,处理完之后打印在另两个个文档,直接复制可能无法运行,需要自己创建三个文档:文档一(源代码);文档二(预处理之后的源代码);文档三(二元组)。记得检查文件位置和名字是否正确。

一、实验目的

设计并实现一个包含预处理功能的词法分析程序,加深对编译中词法分析过程的理解。

二、 实验要求

1、实现预处理功能

源程序中可能包含有对程序执行无意义的符号,要求将其剔除。
首先编制一个源程序的输入过程,从键盘、文件或文本框输入若干行语句,依次存入输入缓冲区(字符型数据);
然后编制一个预处理子程序,去掉输入串中的回车符、换行符和跳格符等编辑性文字;
把多个空白符合并为一个;
去掉注释。

2、实现词法分析功能

输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中,syn为单词种别码。Token为存放的单词自身字符串。Sum为整型常量。
具体实现时,可以将单词的二元组用结构进行处理。

3、待分析的C语言子集的词法(可以自行扩充,也可以按照C语言的词法定义)

1)关键字
main if then while do static int double struct break else long switch case typedef char return const float short continue for void default sizeof do
所有的关键字都是小写。

2)运算符和界符
+ - * / : := < <> <= > >= = ; ( ) #

3)其他标记ID和NUM
通过以下正规式定义其他标记:
ID→letter(letter|digit)*
NUM→digit digit*
letter→a|…|z|A|…|Z
digit→0|…|9…

4)空格由空白、制表符和换行符组成
空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。

4、各种单词符号对应的种别码

表1 各种单词符号的种别码

单词符号 种别码 单词符号 种别码
main 1 ; 41
if 2 ( 42
then 3 ) 43
while 4 int 7
do 5 double 8
static 6 struct 9
ID 25 break 10
NUM 26 else 11
+ 27 long 12
- 28 switch 13
* 29 case 14
/ 30 typedef 15
: 31 char 16
:= 32 return 17
< 33 const 18
<> 34 float 19
<= 35 short 20
> 36 continue 21
>= 37 for 22
= 38 void 23
default 39 sizeof 24
do 40 # 0

5、 词法分析程序的主要算法思想

算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号。

1.主程序示意图
在这里插入图片描述

其中初值包括如下两方面:

(1) 关键字表初值
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关
键字表为一个字符串数组,其描述如下:
char *rwtab[27]={“main”,”if”,”then”,”while”,”do”,” static”,”int”,” double”,”struct”,”break”,”else”,”long”,”switch”,”case”,”typedef”,”char”,”return”,”const”,”float”,”short”,”continue”,”for”,”void”,”default”,”sizeof”,”do”};

(2) 程序中需要用到的主要变量:syn,token和sum。

2.扫描子程序的算法思想

首先设置三个变量:
token用来存放构成单词符号的字符串;
sum用来存放整型单词;
syn用来存放单词符号的种别编码。
扫描子程序主要部分流程如图2所示。
在这里插入图片描述

三、实验代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char key[26][20] = {
    
    "main","if","then","while","do"," static","int"," double","struct","break","else","long","switch","case","typedef","char",
"return","const","float","short","continue","for","void","sizeof","default","do"};
//da yin
void p(char* str)
{
    
    
	printf("%s\n",str);
}
//shan chu kong ge
void deblank(char *str)
{
    
    
	char s[10000];
	char s1[10000]={
    
    NULL};
	int i=0,j=0,next=0;
	strcpy(s,str);
	while(s[j]!=EOF)
	{
    
    
		s1[i]=s[j];
		i++;
		j++;
		if(s[j-1]==' ')
		{
    
    
			next=j;
			while(s[next]==' ')next++;
			j=next;
		}
//		if(s[j]!=' ')
//		{
    
    
//			str[i]=s[j];
//			i++;
//			j++;
//		}
//		else
//		{
    
    
//			str[i]=s[j];
//			i++;
//			j++;
//			next=j;
//			while(s[next]==' ')next++;
//			j=next;
//		}
	}
//	while(str[i++]!='\0')str[i-1]='\0';
	// p(s1);
	strcpy(str,s1);
}
//shan chu zhu shi
void zhushi(char *str)
{
    
    
	int i,j;
	char s[10000];
	strcpy(s,str);
	for(i=0,j=0;s[i]!=EOF;i++,j++)
	{
    
    
		if(s[i]=='/'&&s[i+1]=='/')
		{
    
    
			str[j]=' ';
			while(s[i]!='\n')i++;
		}
		else
		{
    
    
			str[j]=s[i];
		}
	}
	strcpy(s,str);
	for(i=0,j=0;s[i]!=EOF;i++,j++)
	{
    
    
		if(s[i]=='/'&&s[i+1]=='*')
		{
    
    
			str[j]=' ';
			while(s[i]!='*'||s[i+1]!='/')
			{
    
    
				i++;
				if(s[i]==EOF)
				{
    
    
					printf("注释有误。\n");
					system("pause");
					exit(0);
				}
			}
			i=i+1;
		}
		else
		{
    
    
			str[j]=s[i];
		}
	}
	deblank(str);
//	p(str);
}
//shan chu hui che haun hang
void enter(char *str)
{
    
    
	int i,j=0;
	char s[10000];
	strcpy(s,str);
	for(i=0;s[i]!=EOF;i++,j++)
	{
    
    
		if(s[i]=='\n'||s[i]=='\r'||s[i]=='\t')
		{
    
    
			s[i]=' ';
			str[j]=s[i];
		}
		else
		{
    
    
			str[j]=s[i];
		}
	}
	// p(str);
}
int zm(char a)
{
    
    
	if(a>='a'&&a<='z'||a>='A'&&a<='Z')
	{
    
    
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}
int sz(char a)
{
    
    
	if(a>='0'&&a<='9')
	{
    
    
		return 1;
	}
	else
	{
    
    
		return 0;
	}
}

void xr(char *a,int b)
{
    
    
	FILE *fp;
	fp=fopen("D:\\app\\vscode\\codes\\compilation\\exp1-3.txt","a");
	if(fp==NULL)
	{
    
    
		printf("fail to open the file!\n");
		system("pause");
		exit(0);
	}
	if(b>=0)
	{
    
    
		fprintf(fp, "<%s,%d>\n", a, b);
	}
	else
	{
    
    
		fprintf(fp, "无法识别\"%c\"\n",a[0]);
	}
	fclose(fp);
}
void id(char *a)
{
    
    
	int i,b;
	for(i = 0; i<26;i++)
	{
    
    
		if(strcmp(a,key[i]) == 0)
		{
    
    
			if(i<24) 
			{
    
    
				b=i+1;
			}
			else
			{
    
    
				if(i==24) b=39;
				if(i==25) b=40;
			} 
			xr(key[i],b);
			return;
		}
	}
	xr(a,25);
}
void cffx()
{
    
    
	FILE *fp;
	char ch;
	char str[10000];
	char word[50];
	char numb[50];
	int i,j,k;
	fp=fopen("D:\\app\\vscode\\codes\\compilation\\exp1-2.txt","r");
	if(fp==NULL)
	{
    
    
		printf("fail to open the file!\n");
		exit(0);
	}
	i=0;
	while((ch=fgetc(fp))!=EOF)
	{
    
    
		str[i]=ch;
		i++;
	}
	for(i=0,j=0,k=0;str[i]!=NULL;i++)
	{
    
    
		int a,b;
		a=zm(str[i]);
		if(a==1)
		{
    
    
			word[j]=str[i];
			j++;
			for(;;)
			{
    
    
				i++;
				a=zm(str[i]);
				b=sz(str[i]);
				if(a==1||b==1)
				{
    
    
					word[j]=str[i];
					j++;
				}
				else
				{
    
    
					id(word);
					memset(word,0,sizeof(word));
					j=0;
					break;
				}
			}
			i--;
			continue;
		}
		a=sz(str[i]);
		if(a==1)
		{
    
    
			numb[k]=str[i];
			k++;
			for(;;)
			{
    
    
				i++;
				a=sz(str[i]);
				if(a==1||str[i]=='e'||str[i]=='E'||str[i]=='.')
				{
    
    
					if(str[i]=='.'&&sz(str[i+1])==0)
					{
    
    
						printf("小数点错误。\n");
						system("pause");
						exit(0);
					}
					numb[k]=str[i];
					k++;
				}
				else
				{
    
    
					xr(numb,26);
					memset(numb,0,sizeof(numb));
					k=0;
					break;
				}
			}
			i--;
			continue;
		}
		if(str[i]==' ')
		{
    
    
			continue;
		}
		switch(str[i])
		{
    
    
			case '+': xr((char*)"+",27);break;
			case '-': xr((char*)"-",28);break;
			case '*': xr((char*)"*",29);break;
			case '/': xr((char*)"/",29);break;
			case '=': xr((char*)"=",38);break;
			case ';': xr((char*)";",41);break;
			case '(': xr((char*)"(",42);break;
			case ')': xr((char*)")",43);break;
			case '#': xr((char*)"#",0);break;
			case '.': xr((char*)".",-1);break;
			case '{': xr((char*)"{",-1);break;
			case '}': xr((char*)"}",-1);break;
			case '%': xr((char*)"%",-1);break;
			case '\"': xr((char*)"\"",-1);break;
			case '\\': xr((char*)"\\",-1);break;
			case ',': xr((char*)",",-1);break;
			case '|': 
					if(str[i+1] == '|')
					{
    
    
						i++;
						xr((char*)"||",-1);
					}
					else
					{
    
    
						xr((char*)"|",-1);
					}
					break;
			case '&': 
					if(str[i+1] == '&')
					{
    
    
						i++;
						xr((char*)"&&",-1);
					}
					else
					{
    
    
						xr((char*)"&",-1);
					}
					break;
			case ':': 
					if(str[i+1] == '=')
					{
    
    
						i++;
						xr((char*)":=",32);
					}
					else
					{
    
    
						xr((char*)":",31);
					}
					break;
			case '<':
					if(str[i+1] == '>')
					{
    
    
						i++;
						xr((char*)"<>",34);
					}
					else if(str[i+1] == '=')
					{
    
    
						i++;
						xr((char*)"<=",35);
					}
					else
					{
    
    
						xr((char*)"<",33);
					}
					break;
			case '>': 
					if(str[i+1] == '=')
					{
    
    
						i++;
						xr((char*)">=",37);
					}
					else
					{
    
    
						xr((char*)">",36);
					}
					break;
			// default : xr(&str[i],-1);break;
		}	
	}
}

int main()
{
    
    
	FILE *fp;
	char ch;
	char str[10000];
	int i=0; 
	fp=fopen("D:\\app\\vscode\\codes\\compilation\\exp1-1.txt","r");
	if(fp==NULL)
	{
    
    
		printf("fail to open the file!\n");
		exit(0);
	}
	else
	{
    
    
		// printf("The file is open!\n");
		while((ch=fgetc(fp))!=EOF)
		{
    
    
			str[i]=ch;
			i++;
//			putchar(ch);
		}
		// printf("%s\n",str);
		
//		读取文件内容:
//      1. 
//		while((ch=fgetc(fp))!=EOF)putchar(ch);
//		2. 
//		ch=fgetc(fp);
//		while(ch!=EOF)
//		{
    
    
//			putchar(ch);
//			ch=fgetc(fp);
//		}
//		3. 
//		while(!feof(fp))printf("%c",fgetc(fp));
        
//	    while((ch=getchar())!='#')
//        {
    
    
//        	fputc(ch,fp);
//		}

        
        zhushi(str);
        enter(str);
		deblank(str);
//		fclose(fp);
	}
	FILE *fpp;
	fpp=fopen("D:\\app\\vscode\\codes\\compilation\\exp1-2.txt","w");
	if(fpp==NULL)
	{
    
    
		printf("fail to open the file!\n");
		exit(0);
	}
	else
	{
    
    
		// printf("The file is open!\n");
		fputs(str,fpp);
		fclose(fpp);
		fclose(fp);
	}
	FILE *file;
	file = fopen("D:\\app\\vscode\\codes\\compilation\\exp1-3.txt","w");
	fclose(file);
	cffx();
	printf("处理完成\n");
	system("pause");
	return 0;
} 

运行结果:
例子:
/main/
if(a>3)
{
a–;//a>3
}
控制台:
在这里插入图片描述
文档一(源代码):
在这里插入图片描述
文档二(预处理之后的代码):
在这里插入图片描述
文档三(二元组):
在这里插入图片描述
好了,结束,如果不需要中间结果文档二,可以直接注释掉。

猜你喜欢

转载自blog.csdn.net/qq_45750767/article/details/121735645