/* 编译原理实验一:词法分析练习 作者: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; }
编译原理课后练习,词法分析的题目。要求分析一个科学计数的正规式,实在不会化简,就直接写了