📄 lexeme2.c
字号:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define N 512 /*内存缓冲区大小*/
#define M 9 /*标识符的最大长度*/
#define X 1000 /*符号表的最大符号数目*/
#define KEY 0
#define ID 1
#define DIGIT 2
#define CALU 3
#define DIV 4
#define LETTER 5
#define UNDERLINE 6
#define INTERP 7
#define DONE 8
int next=0; /*指向内存缓冲区下一未读的字符*/
int tokenp=0; /*指向字符串数组可放字符位置*/
int length=0; /*符号表中下一存放单词的位置*/
FILE *fp;
char str[N]; /*内存缓冲区*/
char StrToken[M]={'\0'}; /*当前识别的单词*/
int row=1; /*记录行号*/
int tag=0; /*记录该行是否缺少分号*/
struct symbol
{
int classno;
char value[M];
int num;
int bin[16];
};
struct symbol Table[X]; /*符号表结构体数组*/
struct MatchStack /*匹配括号的堆栈结构体*/
{
char ch;
int row;
};
struct MatchStack S[N];
int top=-1;
struct error_information /*检错结构体*/
{
int row;
char info[30];
};
struct error_information error[50];
int errop=0;
int id_keyword(char ch); /*比较关键字表,若单词是关键字返回classno=0,否则返回classno=1*/
void output(); /*输出子程序*/
int identify(char ch); /*当前单词是标识符或关键字*/
int is_id(); /*判断是否为标识符里的关键字函数*/
int caculate(char ch);
int divide(char ch);
int interp(char ch);
int num_bin(char ch);
int identify(char ch) /*判断当前单词是标识符*/
{ StrToken[tokenp]=ch;
tokenp++;
ch=str[next];
next++;
while((str[next]!='\0')&&(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||(ch=='_')||((ch>='0')&&(ch<='9')))&&(tokenp<M))
{ StrToken[tokenp]=ch;
tokenp++;
ch=str[next];
next++;
}
if(str[next]!='\0')
{if(tokenp==M) tokenp--;
next--;
StrToken[tokenp]='\0';
}
else StrToken[tokenp]='\0';
return(ID);
}
int id_keyword(char ch) /*判断当前单词是标识符或关键字*/
{int state=0;
StrToken[tokenp]=ch;
tokenp++;
ch=str[next];
next++;
while((str[next]!='\0')&&(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))&&(tokenp<M)) /*若读入的是字母并且数组未满,则读入数组*/
{StrToken[tokenp]=ch;
tokenp++;
ch=str[next];
next++;
}
if(((ch>='0')&&(ch<='9'))||(ch=='_')) state=identify(ch); /*若读到数字或下划线则表明该字符串为标识符*/
if(ch=='\n')
{
if(tag>1)
{strcpy(error[errop].info,"extra ;\n");
error[errop].row=row;
errop++;
}
row++;
tag=0;
ch=str[next];
next++;
}
if((state==0)&&(str[next]!='\0'))
{if(tokenp==M) tokenp--;
next--;
StrToken[tokenp]='\0';
state=is_id(); /*判断由字母组成的串是关键字还是标识符*/
}
return state;
}
int is_id() /*判断是否为标识符里的关键字函数*/
{int i=31;
char keyword[32][9]={"break","anto","case","char","const","continue","default","do","double","else","enum","extern","float","for","goto","if","int","long","register","return","short","signed","sizeof","static","struct","switch","typedef","union","unsigned","void","volatile","while"};
while((i>=0)&&(strcmp(StrToken,keyword[i]))) i--; /*将读入的字符与关键字数组里的各关键字进行比较,进行判断*/
if(i>=0) return(KEY); /*若相同,则返回值为关键字*/
else return(ID); /*若不同,则返回值为标识符*/
}
int caculate(char ch) /*识别算符的函数*/
{
char c;
StrToken[tokenp]=ch;
tokenp++;
if(str[next]!='\0')
{
c=str[next]; /*next小于内存缓冲区大小N*/
if((ch=='-')&&((c=='>')||(c=='-')||(c=='='))) /*识别“--、->、-=”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if((ch=='+')&&((c=='+')||(c=='='))) /*识别”++、+=“*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if((ch=='<')&&((c=='<')||(c=='='))) /*识别“<<、<=”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if((ch=='>')&&((c=='>')||(c=='='))) /*识别“>>、>=”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if(((ch=='!')||(ch=='=')||(ch=='&')||(ch=='^'))&&(c=='='))/*识别“!、=、&、^、=”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if(((ch=='|')||(ch=='/'))&&(c=='=')) /*识别”/、=、|“*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if(((ch=='*')||(ch=='%'))&&(c=='=')) /*识别“*、%、=”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if((ch=='|')&&(c=='|')) /*识别 “||”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
if((ch=='&')&&(c=='&')) /*识别“&&”*/
{StrToken[tokenp]=ch;tokenp++;next++;}
}
StrToken[tokenp]='\0';
return(CALU);
}
/*识别界符*/
int divide(char ch)
{char c;
if(ch=='('||(ch=='[')||(ch=='{'))
{ top++;
S[top].ch=ch; /*入栈*/
S[top].row=row;
}
if((ch==')')||(ch==']')||(ch=='}'))
{c=S[top].ch;
if(((ch==')')&&(c=='('))||((ch==']')&&(c=='['))||((ch=='}')&&(c=='{'))) {top--;next++;} /*左右界符匹配*/
else
{strcpy(error[errop].info,"right division extra\n");
error[errop].row=row;
errop++;
}
}
if(ch==';') tag++;
StrToken[0]=ch;
StrToken[1]='\0';
return(DIV);
}
int interp(char ch) /*消除注释*/
{ ch=str[next];
next++;
if(ch!='*') return(CALU);
top++;
S[top].ch='/';
S[top].row=row;
top++;
S[top].ch='*';
S[top].row=row;
ch=str[next];
next++;
while((ch!='\0')&&(ch!='*'))
{
while((ch!='*')&&(ch!='\0'))
{ch=str[next];
next++;
}
}
if((ch!='\0')&&(str[next]=='/'))
{next++;
top=top-2;
}
return(DONE);
}
int num_bin(char ch) /*识别常数并转化成二进制*/
{
int num=0,i;
while((ch!='\0')&&(ch>='0')&&(ch<='9'))
{
ch=ch-'0';
num=num*10+ch;
ch=str[next];
next++;
}
next--;
Table[length].num=num;
for(i=0;i<16;i++) { Table[length].bin[i]=0;}
i=15;
while((num!=0)&&(i>=0))
{
Table[length].bin[i]=num%2;
num=num/2;
i--;
}
return(DIGIT);
}
void output() /*输出函数*/
{FILE *fp1,*fp2;
int temp=0,i;
fp1=fopen("d:\\gao\\symbol.txt","wt");
fp2=fopen("d:\\gao\\const.txt","wt");
if(fp1==NULL) printf("write symbol_table error!\n");
if(fp1==NULL) printf("write const_table error!\n");
printf("CLASSNO VALUE LOCATION BINARY\n");
fprintf(fp1,"CLASSNO VALUE\n");
fprintf(fp2,"NUM BINARY\n");
while(temp<length)
{
switch(Table[temp].classno)
{
case KEY : printf("keyword %s\n",Table[temp].value);break;
case ID : printf("ID %s %d\n",Table[temp].value,temp);break;
case DIGIT: printf("DIGIT %d %d ",Table[temp].num,temp);
for(i=0;i<16;i++) printf("%d",Table[temp].bin[i]);
printf("\n");
break;
case CALU : printf("caculate %s\n",Table[temp].value);break;
case DIV : printf("division %s\n",Table[temp].value);break;
default : break;
}
if(Table[temp].classno!=DIGIT) fprintf(fp1,"%d %s\n",Table[temp].classno,Table[temp].value);
else {
fprintf(fp2,"%d ",Table[temp].num);
for(i=0;i<16;i++) fprintf(fp2,"%d",Table[temp].bin[i]);
fprintf(fp2,"\n");
}
temp++;
}
fclose(fp1);
fclose(fp2);
while(top!=-1) /*左界符多余*/
{strcpy(error[errop].info,"left division extra\n");
error[errop].row=S[top].row;
top--;
errop++;
}
if(errop>0) /*若无错误信息,则errop为零*/
{printf("ERROR INFORMATION:\n");
temp=0;
while(temp<errop)
{
printf("line:%d ",error[temp].row);
printf("%s\n",error[temp].info);
temp++;
}
}
}
int main(int argc,char *argv[])
{char ch;
int initstate,classno,i;
fp=fopen(argv[1],"rt");
if(fp==NULL)
{printf("不能打开此文件!");
}
while(!feof(fp))
{fread(str,N,1,fp);
puts(str);
}
ch=str[next];
next++;
while(ch!='\0')
{if(ch=='\n')
{
if(tag>1)
{strcpy(error[errop].info,"extra ;\n");
error[errop].row=row;
errop++;
}
row++;
tag=0;
ch=str[next];
next++;
classno=DONE;
initstate=10;
}
if(ch==' ')
{ch=str[next];
next++;
classno=DONE;
initstate=10;
}
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) initstate=LETTER; /*以字母开头的字符串,开始识别标识符或关键字*/
if(ch=='_') initstate=UNDERLINE; /*以下划线开头的字符串,开始识别标识符*/
if((ch=='-')||(ch=='.')||(ch=='!')||(ch=='~')||(ch=='+')||(ch=='*')||(ch=='&')||(ch=='/')||(ch=='%')||(ch=='<')||(ch=='>')||(ch=='^')||(ch=='|')||(ch=='=')||(ch=='?')||(ch=='=')) initstate=CALU;
if((ch=='[')||(ch=='(')||(ch==')')||(ch=='{')||(ch=='}')||(ch==']')||(ch==',')||(ch==';')||(ch=='"')) initstate=DIV;
if(ch=='/') initstate=INTERP;
if((ch>='0')&&(ch<='9')) initstate=DIGIT;
switch(initstate)
{case LETTER: classno=id_keyword(ch); break;
case UNDERLINE: classno=identify(ch); break;
case CALU: classno=caculate(ch); break;
case DIV: classno=divide(ch); break;
case INTERP: classno=interp(ch); break;
case DIGIT: classno=num_bin(ch); break;
default : break;
}
if(classno!=DONE)
{Table[length].classno=classno; /*把识别出的标识符或关键字放入符号表*/
if(classno!=DIGIT)
{strcpy(Table[length].value,StrToken);
for(i=0;i<M;i++) StrToken[i]='\0';
tokenp=0;
}
length++;
}
ch=str[next];
next++;
}
fclose(fp);
output();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -