此语法分析程序的基本词法分析能够识别基本字、标识符、有符号整数、有符号浮点数、运算符和界符)。
语法结构定义 ::= { +|-} ::= {*|/} ::=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"); else printf("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; } }