zoukankan      html  css  js  c++  java
  • 编译原理词法分析

    /*
    编译原理实验一:词法分析练习
    作者:李全锋
    时间: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("
    按Esc退出,其他键继续...
    ");
    		
    		if(!kbhit()){
    			key=getch();
    		}
    	}while(key!=K_ESC);
    
    	return 0; 
    } 
    
    //输入字符串并进行词法分析,返回二元组 
    void analytics(){
    	ptrp=0;
    	printf("请输入字符串,以#结尾:
    ");
    	do{
    		ch=getchar();
    		prog[ptrp++]=ch;
    
    			
    	}while(ch!='#');
    	ptrp=0;
    	do{
    		scanner();
    		switch(syn){
    			case 1:printf("(%2d,%8s)
    ",syn,token);break;
    			case 2:printf("(%2d,%8s)
    ",syn,token);break;
    			case 3:printf("(%2d,%8s)
    ",syn,token);break;
    			case 4:printf("(%2d,%8s)
    ",syn,token);break;
    			case 5:printf("(%2d,%8s)
    ",syn,token);break;
    			case 6:printf("(%2d,%8s)
    ",syn,token);break;
    			case 10:printf("(%2d,%8s)
    ",syn,token);break;
    			case 11:printf("(%2d,%lg)
    ",syn,sum);break;
    			case 13:printf("(%2d,%8s)
    ",syn,token);break;
    			case 14:printf("(%2d,%8s)
    ",syn,token);break;
    			case 15:printf("(%2d,%8s)
    ",syn,token);break;
    			case 16:printf("(%2d,%8s)
    ",syn,token);break;
    			case 17:printf("(%2d,%8s)
    ",syn,token);break;
    			case 18:printf("(%2d,%8s)
    ",syn,token);break;
    			case 20:printf("(%2d,%8s)
    ",syn,token);break;
    			case 21:printf("(%2d,%8s)
    ",syn,token);break;
    			case 22:printf("(%2d,%8s)
    ",syn,token);break;
    			case 23:printf("(%2d,%8s)
    ",syn,token);break;
    			case 24:printf("(%2d,%8s)
    ",syn,token);break;
    			case 25:printf("(%2d,%8s)
    ",syn,token);break;
    			case 26:printf("(%2d,%8s)
    ",syn,token);break;
    			case 27:printf("(%2d,%8s)
    ",syn,token);break;
    			case 28:printf("(%2d,%8s)
    ",syn,token);break;
    			
    			case 0:break;//#
    			case -1:printf("输入有误!");break;
    			default:printf("(%2d,%8s)
    ",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;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    


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

  • 相关阅读:
    Largest Rectangle in Histogram
    Valid Sudoku
    Set Matrix Zeroes
    Unique Paths
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Path Sum II
    Path Sum
    Validate Binary Search Tree
    新手程序员 e
  • 原文地址:https://www.cnblogs.com/james1207/p/3347911.html
Copyright © 2011-2022 走看看