编译原理词法分析

/*
编译原理实验一:词法分析练习
作者:lqf
时间: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;
}




















编译原理课后练习,词法分析的题目。要求分析一个科学计数的正规式,实在不会化简,就直接写了
上一篇:精通css(2)-选择器


下一篇:使用 HTML、CSS 和 JavaScript 制作模拟时钟(初学者教程01)