编译原理之设计扫描器,请问哪里有问题怎么改,为什么死循环 5C

#include "string.h"
#include "math.h"
#include "stdio.h"
char keywords[30][12]={"program","begin","end","var","while","do","repeat",
"until","for","to","if","then","else",";", ":", "(", ")", ",",
":=", "+", "-", "*", "/", ">", ">=", "==", "<", "<="};
int num_key=28;
int aut[11][8]={ 0, 0, 0, 0, 0, 0, 0, 0,
0, 2, 0, 0, 0, 8, 9,15,
0, 2, 3, 5,11, 0, 0,11,
0, 4, 0, 0, 0, 0, 0, 0,
0, 4, 0, 5,11, 0, 0,11,
0, 7, 0, 0, 6, 0, 0, 0,
0, 7, 0, 0, 0, 0, 0, 0,
0, 7, 0, 0,11, 0, 0,11,
0, 8, 0, 0, 0, 8, 0,12,
0, 0, 0, 0, 0, 0,10,14,
0, 0, 0, 0, 0, 0, 0,13};
char ID[50][12];
int C[20];
int num_ID=0,num_C=0;

struct token
{ int code;
int value;
}; //Token结构
struct token tok[100]; //Token数组
int i_token=0,num_token=0; //Token计数器和Token个数
char strTOKEN[15]; //当前单词
int i_str; //当前单词指针
int n,p,m,e,t; //尾数值,指数值,小数位数,指数符号,类型
double num; //常数值
char w[50]; //源程序缓冲区
int i; //源程序缓冲区指针,当前字符为w[i]

struct map //当前字符到状态转换矩阵列标记的映射
{
char str[50];
int col;
};
struct map col1[4]={{"0123456789",1},{".",2},{"Ee",3},{"+-",4}}; //数字
struct map col2[2]={{"abcdefghijklmnopqrstuvwxyz",5},{"0123456789",1}}; //关键字或标识符
struct map col3[1]={{";:(),+-*/=><",6}}; //界符
struct map *ptr;
int num_map;

void act(int s);
int find(int s,char ch);
int InsertConst(double num);
int Reserve(char *str);
int InsertID(char *str);

int main(int argc, char* argv[])
{
FILE *fp;
int s; //当前状态
fp=fopen("exa.txt","r");
while (!feof(fp))
{
fgets(w,50,fp);
i=0;
do
{
while (w[i]==' ') //滤空格
i++;

if (w[i]>='a' && w[i]<='z')                     //判定单词类别
{
    ptr=col2;  num_map=2;
}
else if (w[i]>='0' && w[i]<='9')
{
    ptr=col1;  num_map=4;
}
else if (strchr(col3[0].str,w[i])==NULL)
{
    printf("非法字符%c\n",w[i]);
    i++;
    continue;
}
else
{
    ptr=col3;  num_map=1;
}

i--;
s=1;                                   //开始处理一个单词
while (s!=0)
{
    act(s);
    if (s>=11 && s<=14)
        break;
    i++;                                  //getchar()
    s=find(s,w[i]);
}
if (s==0)
{
    strTOKEN[i_str]='\0';
    printf("词法错误:%s\n",strTOKEN);
}

}while (w[i]!=10);
}

printf("关键字表:");                        //输出结果
for (i=0;i<30;i++)
    printf("%s ",keywords[i]);
printf("\n");
printf("Token序列:");
for (i=0;i<num_token;i++)
    printf("(%d,%d)",tok[i].code,tok[i].value);
printf("\n");
printf("符号表:");
for (i=0;i<num_ID;i++)
    printf("%s ",ID[i]);
printf("\n");
printf("常数表:");
for (i=0;i<num_C;i++)
    printf("%d ",C[i]);
printf("\n");

fclose(fp);
printf("Hello World!\n");
return 0;

}

void act(int s)
{
int code;
switch (s)
{
case 1:n=0;m=0;p=0;t=0;e=1;num=0;i_str=0;
strTOKEN[i_str]='\0'; //其它变量初始化
break;
case 2:n=10*n+w[i]-48;
break;
case 3:t=1;
break;
case 4:n=10*n+w[i]-48; m++;
break;
case 5:t=1;
break;
case 6:if (w[i]=='-') e=-1;
break;
case 7:p=10*p+w[i]-48;
break;
case 8:strTOKEN[i_str++]=w[i]; //将ch中的符号拼接到strTOKEN的尾部;
break;
case 9:strTOKEN[i_str++]=w[i]; //将ch中的符号拼接到strTOKEN的尾部;
break;
case 10:strTOKEN[i_str++]=w[i]; //将ch中的符号拼接到strTOKEN的尾部;
break;
case 11:num=n*pow(10,e*p-m); //计算常数值
tok[i_token].code=2; tok[i_token++].value=InsertConst(num); //生成常数Token
num_token++;
break;
case 12:strTOKEN[i_str]='\0';
code=Reserve(strTOKEN); //查关键字表
if (code)
{ tok[i_token].code=code; tok[i_token++].value=0; } //生成关键字Token
else
{ tok[i_token].code=1;

tok[i_token++].value=InsertID(strTOKEN); } //生成标识符Token
num_token++;
break;
case 13:strTOKEN[i_str]='\0';
code=Reserve(strTOKEN); //查界符表
if (code)
{ tok[i_token].code=code; tok[i_token++].value=0; } //生成界符Token
else
{
strTOKEN[strlen(strTOKEN)-1]='\0'; //单界符
i--;
code=Reserve(strTOKEN); //查界符表
tok[i_token].code=code; tok[i_token++].value=0; //生成界符Token
}
num_token++;
break;
case 14:strTOKEN[i_str]='\0';
code=Reserve(strTOKEN); //查界符表
tok[i_token].code=code; tok[i_token++].value=0; //生成界符Token
num_token++;
break;
}
}
int find(int s,char ch)
{
int i,col=7;
struct map *p;
p=ptr;
for (i=0;i if (strchr((p+i)->str,ch))
{
col=(p+i)->col;
break;
}
return aut[s][col];
}
int InsertConst(double num)
{
int i;
for (i=0;i<num_C;i++)
if (num==C[i])
return i;
C[i]=num;
num_C++;
return i;
}

int Reserve(char *str)
{
int i;
for (i=0;i<num_key;i++)
if (!strcmp(keywords[i],str))
return (i+3);
return 0;
}

int InsertID(char *str)
{
int i;
for (i=0;i<num_ID;i++)
if (!strcmp(ID[i],str))
return i;
strcpy(ID[i],str);
num_ID++;
return i;
}

1个回答

编译原理大致分两部分,第一部分是词法分析,即把字节流(byte stream) 识别位记号流(token stream),第二部分是语法分析,即抽象语法树(abstract syntax tree)。其中第一部分词法分析普遍采用有限状态自动机,有限状态自动机又分两种,确定型和非确定型。您看看需不需要重写。

FORESTAPE
学海舟舟_林 不晓得哪里出了问题,不重写了
大约 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐