1. 程式人生 > >最簡單的詞法分析器

最簡單的詞法分析器

1、 實驗目的:

設計、編制、除錯一個詞法分析程式,對單詞進行識別和編碼,加深對詞法分析原理的理解。

2、 實驗要求

(1) 允許使用者自己輸入源程式並儲存為檔案

(2) 系統能夠輸出經過預處理後的源程式(去掉註釋、換行、空格等)

(3) 能夠將該源程式中所有的單詞根據其所屬型別(整數、保留字、運算子、識別符號等。定義的類C語言中的識別符號只能以字母或下劃線開頭)進行歸類顯示,例如:識別保留字:ifintforwhiledoreturnbreakcontinue等,其他的都識別為識別符號;常數為無符號整形數;運算子包括:+-*/=><>=<=

!=等;分隔符包括:,;{}()等。

實現檔案的讀取操作,而不是將文字以字串形式預存於程式中。文字內容為待分析的類C語言程式。

設計並實現一個詞法分析器,實現對指定位置的類C語言源程式文字檔案的讀取,並能夠對該源程式中的所有單詞進行分類,指出其所屬型別,實現簡單的詞法分析操作。

例如下面為一段C語言源程式:

main()

{

int  a,b;

a = 10;

b = a + 20;

}

要求輸出如下

(1,’main’)

(5,’(’)

(5,’)’)

(5,’{ ’)

(1,’int’)

(2,’a’)

(5,’,’)

(2,’b’)

(5,’;’)

(2,’a’)

(4,’=’)

(3,’10’)

(5,’;’)

(2,’b’)

(4,’=’)

(2,’a’)

(4,’+’)

(3,’20’)

(5,’;’)

(5,’}’)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct Word
{
	int num;//詞所屬型別
	char w[20];//詞
}Word;

int main()
{
	char ch,word_temp[20]="";
	int i=0,j=0,k=0,key=0,chioce;
	char ktt[28][20]={"int","do","else","main","if","while","break","continue","for","return",
	",",";",":","(",")","[","]","{","}","+","-","*","/","=","<",">","<=",">="};
	FILE *fp;
	Word word[100];
	printf("1:輸入源程式儲存成檔案\n");
	printf("2:開啟檔案進行詞法分析\n");
	printf("請輸入你的選擇:");
	scanf("%d",&chioce);
	switch(chioce)
	{
	case 1:
		fp=fopen("F:\\程式設計小試\\C語言\\詞法分析\\C_program.txt","w");
		if(!fp)
		{
			printf("can't open file C_program.txt\n");
			exit(1);
		}
		printf("請輸入一段程式(以#結束):\n");
		ch=getchar();
		while(ch!='#')
		{
			fputc(ch,fp);
			ch=getchar();
		}
		fclose(fp);break;
	case 2:
		fp=fopen("F:\\程式設計小試\\C語言\\詞法分析\\C_program.txt","r");
		if(!fp)
		{
			printf("can't open file C_program.txt\n");
			exit(1);
		}
		printf("源程式如下:");
		while((ch=fgetc(fp))!=EOF)
		{
			putchar(ch);
		}
		fclose(fp);
		printf("\n詞法分析結果如下:\n");
		fp=fopen("F:\\程式設計小試\\C語言\\詞法分析\\C_program.txt","r");
		if(!fp)
		{
			printf("can't open file C_program.txt\n");
			exit(1);
		}
		while((ch=fgetc(fp))!=EOF)
		{   
			if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
			{
				
				word_temp[key++]=ch;//連續幾個字母的連成單詞
				word_temp[key]='\0';
				continue;
			}
			else
			{   if(strcmp(word_temp,"")!=0)
				{
					strcpy(word[i].w,word_temp);//將單詞拷貝到結構陣列中
					strcpy(word_temp,"");
					key=0;//回到臨時陣列的開始位置
					i++;//結構陣列的下標加1
					
				}
				if(ch==' '||ch==10||ch=='	')//去掉空格、回車和tab鍵
				{	
					continue;
				}			
				else
				{
					word_temp[0]=ch;
					word_temp[1]='\0';//字串結束符
					strcpy(word[i].w,word_temp);//將非字母數字符號拷貝到結構陣列中
					strcpy(word_temp,"");
					key=0;//回到臨時陣列的開始位置
					i++;
				}
			}
		}break;
	default: printf(" 輸入錯誤!");
	}
	
	for(j=0;j<i;j++)
	{
		for(k=0;k<28;k++)
		{
			if((strcmp(word[j].w,ktt[k]))==0)
			{
				if(k>=0&&k<10)
					word[j].num=1;//保留字
				else if(k>=10&&k<19)
					word[j].num=5;//分隔符
				else if(k>=19&&k<28)
					word[j].num=4;//運算子
				else if(word[j].w[0]>='0'&&word[j].w[0]<='9')
					word[j].num=3;//數字
				break;
			}
			else 
				word[j].num=2;//變數
		}
	}
	for(j=0;j<i;j++)//按格式要求列印輸出
	{
		printf("(%d,'%s')\n",word[j].num,word[j].w);
	}


	fclose(fp);
	return 0;
}