编译原理词法分析

/*

编译原理实验一:词法分析练习

作者:李全锋

时间:2013-9-28 

*/

#include <stdio.h>

#include <conio.h>

#include <string.h>



#define TOKENMAX 100

#define PROGMAX 1000 

#define K_ESC   27

void analytics();      //词法分析

void scanner();        //输入扫描

bool isLetter(char ch);//判断字符是否为字母 

bool isDigit(char ch);//判断字符是否为数字

bool concat(char token[],char ch);//将ch连接在token后面 

int reserve(char token[]);//对token中字符串查关键字表,若是关键字返回其编码,否则返回标识符种别码10

double ezhishu(int x,double e);//求以e为底的指数

bool isZheng11();//11正规式判断,判断是否是(+|-)d+(.d+)(ed+)的科学计数

//全局变量

char prog[PROGMAX],token[TOKENMAX];

char ch;

int syn,ptrp,ptrt;//ptrp是缓冲区prog的指针//ptrt是token的指针

double sum;

char *rwtab[6]={"begin","if","then","while","do","end"};



int main(){

	int key=0;

	do{

		fflush(stdin);//清空输入流

		analytics();

		printf("\n按Esc退出,其他键继续...\n");

		

		if(!kbhit()){

			key=getch();

		}

	}while(key!=K_ESC);



	return 0; 

} 



//输入字符串并进行词法分析,返回二元组 

void analytics(){

	ptrp=0;

	printf("请输入字符串,以#结尾:\n");

	do{

		ch=getchar();

		prog[ptrp++]=ch;



			

	}while(ch!='#');

	ptrp=0;

	do{

		scanner();

		switch(syn){

			case 1:printf("(%2d,%8s)\n",syn,token);break;

			case 2:printf("(%2d,%8s)\n",syn,token);break;

			case 3:printf("(%2d,%8s)\n",syn,token);break;

			case 4:printf("(%2d,%8s)\n",syn,token);break;

			case 5:printf("(%2d,%8s)\n",syn,token);break;

			case 6:printf("(%2d,%8s)\n",syn,token);break;

			case 10:printf("(%2d,%8s)\n",syn,token);break;

			case 11:printf("(%2d,%lg)\n",syn,sum);break;

			case 13:printf("(%2d,%8s)\n",syn,token);break;

			case 14:printf("(%2d,%8s)\n",syn,token);break;

			case 15:printf("(%2d,%8s)\n",syn,token);break;

			case 16:printf("(%2d,%8s)\n",syn,token);break;

			case 17:printf("(%2d,%8s)\n",syn,token);break;

			case 18:printf("(%2d,%8s)\n",syn,token);break;

			case 20:printf("(%2d,%8s)\n",syn,token);break;

			case 21:printf("(%2d,%8s)\n",syn,token);break;

			case 22:printf("(%2d,%8s)\n",syn,token);break;

			case 23:printf("(%2d,%8s)\n",syn,token);break;

			case 24:printf("(%2d,%8s)\n",syn,token);break;

			case 25:printf("(%2d,%8s)\n",syn,token);break;

			case 26:printf("(%2d,%8s)\n",syn,token);break;

			case 27:printf("(%2d,%8s)\n",syn,token);break;

			case 28:printf("(%2d,%8s)\n",syn,token);break;

			

			case 0:break;//#

			case -1:printf("输入有误!");break;

			default:printf("(%2d,%8s)\n",syn,token);



		}

	}while(syn!=0 && syn!=-1);	

}



void scanner(){

	int n;

	for(n=0;n<TOKENMAX;n++) token[n]=NULL;

	ch=prog[ptrp++];

	n=0;

	while((ch==32 || ch==10) && n++<PROGMAX)ch=prog[ptrp++];

	

	if(isLetter(ch)){		

		//文法10

		int temp=ptrp;

		while(isDigit(ch) || isLetter(ch)){

			concat(token,ch);

			ch=prog[ptrp++];

		}

		ptrp--;

		for (n=0;n<6;n++){

      	   if(strcmp(token,rwtab[n])==0)

           {  

           	   switch(n){

           	   	case 0:syn=1;return;

				case 1:syn=2;return;

				case 2:syn=3;return;

				case 3:syn=4;return;

				case 4:syn=5;return;

			    case 5:syn=6;return;

				

				}

		   }

       }

		if(temp<=ptrp){

			syn=10;			

			return;

		}

	  

   }

   else	{

		if(isDigit(ch))

			{  

				int temp=ptrp;

				if(isZheng11()){

					syn=11;

					return;

				}

				ptrp=temp;

			}

			switch(ch){

				case '<':

					ptrt=0;

					token[ptrt++]=ch;

					ch=prog[ptrp++];

					if (ch=='>')

					{  syn=21;

					    token[ptrt++]=ch;

					}

					else if (ch=='=')

					{  

						syn=22;

					    token[ptrt++]=ch;

				    }

					else

					{ 

						syn=20;

						ptrp--;

					}

					break;

				case '>':

					ptrt=0;

					token[ptrt++]=ch;

					ch=prog[ptrp++];

					if (ch=='=')

					{  syn=24;

					    token[ptrt++]=ch;

					}

					else

					{ 

						syn=23;

						ptrp--;

					}

					break;

				case '+':

					ptrt=0;

					token[ptrt++]=ch;

					ch=prog[ptrp++];

					if(isDigit(ch)){

						if(isZheng11()){

							syn=11;

							return;

						}

					}

					else{

						syn=13; token[0]='+';ptrp--; return;

					}

				case '-':

					ptrt=0;

					token[ptrt++]=ch;

					ch=prog[ptrp++];

					if(isDigit(ch)){

						if(isZheng11()){

							syn=11;

							sum-=2*sum;

							return;

						}

					}

					else{

						syn=14; token[0]='-';ptrp--; return;

					}

				case '*':syn=15; token[0]=ch; return;

				case '/':syn=16; token[0]=ch; return;

				case ':':

					ptrt=0;

					token[ptrt++]=ch;

					ch=prog[ptrp++];

					if (ch=='=')

					{  syn=18;

					    token[ptrt++]=ch;

					}

					else

					{ 

						syn=17;

						ptrp--;

					}

					return;

				case '(':syn=27; token[0]=ch; return;

				case ';':syn=26; token[0]=ch; return;

				case '=':syn=25; token[0]=ch; return;

				case ')':syn=28; token[0]=ch; return;

				case '#':syn=0;  token[0]=ch; return;

				default: 

					

				    syn= -1;  token[0]=ch;return ;



			}

		



   } 



}

bool isLetter(char ch){

	return ((ch >64 && ch <91) || (ch >96 && ch <123));

}

bool isDigit(char ch){

	return (ch >47 && ch <58);

}

bool concat(char token[],char ch){

	int i=0;

	while(i< TOKENMAX){

		if(token[i] == NULL){

			token[i]=ch;

			return true;

		}

		i++;

	}

	return false;

}



bool isZheng11(){

	int temp1=ptrp;

	int temp2=ptrp;

	sum=0;

	while(isDigit(ch)){

		sum=sum*10+ch-'0';

		ch=prog[ptrp++];

	}

	temp1=--ptrp;

	if(ch=='.'){

		//xiaoshu

		ch=prog[++temp1];

		double dot=0.1;

		while(isDigit(ch)){

			sum=(ch-'0')*dot+sum;

			ch=prog[++temp1];

			dot*=0.1;

		}

		

		if(ch=='e'){//kexue

			ch=prog[++temp1];

			temp2=temp1;

			int tempsum=0;

			if(isDigit(ch)){

				while(isDigit(ch)){

					tempsum=10*tempsum+ch-'0';

					//sum=sum*ezhishu((ch-'0'),10);

					ch=prog[++temp1];

				}

				if(temp2<temp1){

					sum=sum*ezhishu(tempsum,10);

					ptrp=temp1;

					return true;

				}

				ch='e';

			}

			else if(ch=='+'){

				ch=prog[++temp1];

				temp2=temp1;

				int tempsum=0;

				while(isDigit(ch)){

					tempsum=tempsum*10+ch-'0';

					//sum=sum*ezhishu(ch-'0',10);

					ch=prog[++temp1];

				}

				if(temp2<temp1){

					sum=sum*ezhishu(tempsum,10);

					ptrp=temp1;

					return true;

				}

				ch='+';

			}

			else if(ch=='-'){

				ch=prog[++temp1];

				temp2=temp1;

				int tempsum=0;

				while(isDigit(ch)){

					tempsum=tempsum*10+ch-'0';

					//sum=sum*ezhishu(ch-'0',0.1);

					ch=prog[++temp1];

				}

				if(temp2<temp1){

					sum=sum*ezhishu(tempsum,0.1);

					ptrp=temp1;

					return true;

				}

				ch='-';

		

			}

			else{

			}

			ptrp=temp2-1;

		

		}

		else if(temp1>=ptrp){

			ptrp=temp1;

			return true;

		}

		else{

			

		}

	}

	else if(ch=='e'){

		//kexue jishu

		ch=prog[++temp1];

		temp2=temp1;

		int tempsum=0;

		if(isDigit(ch)){

			

			while(isDigit(ch)){

				tempsum=10*tempsum+ch-'0';

				//sum=sum*ezhishu((ch-'0'),10);

				ch=prog[++temp1];

			}



			if(temp2<temp1){

				sum=sum*ezhishu(tempsum,10);

				ptrp=temp1;

				return true;

			}

			ch='e';

		}

		else if(ch=='+'){

			ch=prog[++temp1];

			temp2=temp1;

			int tempsum=0;

			while(isDigit(ch)){

				tempsum=tempsum*10+ch-'0';

				//sum=sum*ezhishu(ch-'0',10);

				ch=prog[++temp1];

			}

			if(temp2<temp1){

				sum=ezhishu(tempsum,10)*sum;

				ptrp=temp1;

				return true;

			}

			ch='+';

		}

		else if(ch=='-'){

			ch=prog[++temp1];

			temp2=temp1;

			while(isDigit(ch)){

			sum=sum*ezhishu(ch-'0',0.1);

			ch=prog[++temp1];

			}

			if(temp2<temp1){

				ptrp=temp1;

				return true;

			}

			ch=temp1-2;

			ch='-';

		}

		else{

		}

		ch='e';

	}

	else{

		//zhengshu

		

	}

	return true;

}



double ezhishu(int x,double e){

	double sum=1;

	for(;x-->0;sum*=e);

	return sum;

}








































编译原理课后练习,词法分析的题目。要求分析一个科学计数的正规式,实在不会化简,就直接写了

你可能感兴趣的:(编译原理)