能识别浮点数的简单语法分析程序(C语言实现)
此语法分析程序的基本词法分析能够识别基本字、标识符、有符号整数、有符号浮点数、运算符和界符)。
?
语法结构定义 ::= { +|-} ::= {*|/} ::=ID|num|()num::= ( +|-|ε ) 数字数字*(.数字数字* | ε)( e ( +|-|ε ) 数字数字*|ε)ID::=字母(字母|数字)*字母::=a|b|c…|z|A|B|C…|Z数字::=0|1|2…|9
?
词法分析程序需具备词法分析的功能:输入:所给文法的源程序字符串。(字符串以“#”号结束)输出:success 是文法正确句子;error 不是文法正确句子例如:输入 a+b*c# 输出success.
?
参考输入字符串:
?
(+123.456+-456.789e-120)*m2+(a++456)*c123
(+123.456+-456.789e-120)*m2+(a++456)*-123
(+123.456+-456.789e-120)*m2+(a++456)*-c123(标识符前加负号,输出error)
d+-11.7e-17
a+-149+49.7e+127+-m123(标识符前加负号,输出error)
a+-149+49.7e+127+m123
((a+b)*-14.79e+127)*379+m32
A+-128e-127-b21
A+-128e-127+-6
?
实现截图:
?
?
源代码:
?
?
#include<stdio.h>#include<string.h>int isError;char prog[80]; //存放所有输入字符 char token[8]; //存放词组 char ch; //单个字符 int syn,p,m,n; //syn:种别编码 double sum; int count; int isSignal; //是否带正负号(0不带,1负号,2正号)int isDecimal; //是否是小数 double decimal; //小数 int isExp; //是否是指数 int index; //指数幂 int isNegative; //是否带负号 double temp; int temp2;int repeat; //是否连续出现+,- void scanner(); char *rwtab[9]={"main","int","float","double","char","if","else","do","while"};void E();void T();void F();void scanner();void main(){p=0;count=0;isDecimal=0;index=0;repeat=0;printf("\n please input the source string:\n");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;isError=0;scanner();if((syn==20)||(syn==10)||(syn==26)) {E();}if((ch=='#')&&(isError==0))printf("success\n");elseprintf("error\n");}void E(){T();while((syn==22)||(syn==23)){scanner();T();}}void T(){F();while((syn==24)||(syn==25)){scanner();F();}}void F(){if((syn==20)||(syn==10))scanner();else if(syn==26){scanner();E();if(syn==27){scanner();}else isError=1;}else isError=1;}void scanner() { sum=0; decimal=0; m=0; for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; //从prog中读出一个字符到ch中 while(ch==' ') //跳过空字符(无效输入) ch=prog[p++]; if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) //ch是字母字符 { while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9'))) { token[m++]=ch; //ch=>token ch=prog[p++]; //读下一个字符 } token[m++]='\0'; p--; //回退一格 syn=10; //标识符 //如果是"begin","if","then","while","do","end"标识符中的一个 for(n=0;n<9;n++) if(strcmp(token,rwtab[n])==0) { syn=n+1; break; } } else if((ch>='0')&&(ch<='9')) { IsNum: if(isSignal==1) { //token[m++]='-'; } while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的 ch=prog[p++]; } if(ch=='.') { isDecimal=1; ch=prog[p++]; count=0; //之前忘了清零,123.123+123.123#两个浮点数就无法识别 while((ch>='0')&&(ch<='9')) { //pow(x,y)计算x的y次幂 temp=(ch-'0')*pow(0.1,++count); decimal=decimal+temp; //AddToDec(); ch=prog[p++]; } sum=sum+decimal; } if(ch=='e'||ch=='E') { isExp=1; ch=prog[p++]; if(ch=='-') { isNegative=1; ch=prog[p++]; } while((ch>='0')&&(ch<='9')) { //指数 index=index*10+ch-'0'; ch=prog[p++]; } //10的幂 //123e3代表123*10(3) //sum=sum*pow(10,index);是错误的 if(isNegative) sum=sum*pow(0.1,index); else sum=sum*pow(10,index); } if(isSignal==1){sum=-sum;isSignal=0;} p--; syn=20; } else switch(ch) { case '<': m=0; token[m++]=ch; ch=prog[p++]; if(ch=='=') { syn=35; token[m++]=ch; } else { syn=34; p--; } break; case '>': m=0; token[m++]=ch; ch=prog[p++]; if(ch=='=') { syn=33; token[m++]=ch; } else { syn=32; p--; } break; case '=': m=0; token[m++]=ch; ch=prog[p++]; if(ch=='=') { syn=36; token[m++]=ch; } else { syn=21; p--; } break; case '+':temp2=prog[p];token[m++]=ch;if((temp2>='0')&&(temp2<='9')&&(repeat==1)){isSignal=2;ch=prog[p++];repeat=0;goto IsNum;}if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) //如果重复出现符号,才将后边的+,-视为正负号{repeat=1;//ch=prog[p++];}syn=22;break;case '-':temp2=prog[p];token[m++]=ch;if((temp2>='0')&&(temp2<='9')&&(repeat==1)){isSignal=1;ch=prog[p++]; //读“-”下一个字符repeat=0;goto IsNum; //转到数字的识别}if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) //如果重复出现符号,才将后边的+,-视为正负号{repeat=1; //预言会重复//ch=prog[p++]; //读下一个字符}syn=23;break; /* case '*': syn=24; token[m++]=ch; break;*/case '*':temp2=prog[p];token[m++]=ch;if(temp2=='+'){isSignal=2;repeat=1;}else if(temp2=='-'){isSignal=1;repeat=1;}syn=24;break; case '/': syn=25; token[m++]=ch; break; /* case '(': syn=26; token[m++]=ch; break;*/case '(':temp2=prog[p];token[m++]=ch;if(temp2=='+'){isSignal=2;repeat=1;}else if(temp2=='-'){isSignal=1;repeat=1;}syn=26;break; case ')': syn=27; token[m++]=ch; break; case '{': syn=28; token[m++]=ch; break; case '}': syn=29; token[m++]=ch; break; case ',': syn=30; token[m++]=ch; break; case ';': syn=31; token[m++]=ch; break; case'#': syn=0; token[m++]=ch; break; default: syn=-1; } }