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