?? scan.cpp
字號:
#include"scan.h"
char ch,ch1;//從文件中讀取一個字符
int row=1;//正在讀取的字符的行號
int R=0;//括號匹配中用于記錄棧頂位置
char parRight[20];//棧,用與括號匹配
FILE *sourceFile;//要分析的文件
FILE *inFile;//關鍵字和保留字的文檔
FILE *keyFile;//關鍵字和保留字的文檔
symble symbleList[30];//用與存儲關鍵字和保留字的結構體數組
token currentToken;
int Token_Number=0;
/*如果輸入的符號是左括號中的一種,則將其存入數組中,如果是右括號,則進行以下的判定:\
1:數組中元素是否為空,為空,表明不匹配
2:數組中的元素不為空,則數組中的最后一個元素和當前的元素是否為匹配的左右元素的關系,
若是,則將數組的最后一個元素置為'\0*/
void kuahao(char ch1)
{
int i;
char ch=ch1;
if((ch=='(')||(ch=='[')||(ch=='{'))//左向括號,進入數組
{
parRight[R++]=ch;
printf("\n");
}
if(ch==')')
{
i=R-1;
if((parRight[i]=='\0')||(parRight[i]!='('))
{
printf("此處括號是不匹配的! \n");
}
if(parRight[i]=='(')
{
parRight[i]='\0';
printf("\n");
R--;
}
}
if(ch==']')
{
i=R-1;
if((parRight[i]=='\0')||(parRight[i]!='['))
{
printf("此處括號是不匹配的! \n");
}
if(parRight[i]=='[')
{
parRight[i]='\0';
printf("\n");
R--;
}
}
if(ch=='}')
{
i=R-1;
if((parRight[i]=='\0')||(parRight[i]!='{'))
{
printf("此處括號是不匹配的! \n");
}
if(parRight[i]=='{')
{
parRight[i]='\0';
printf("\n");
R--;
}
}
}
/************************判定是否為數字****************************/
void IsNumber()
{
int k=0;
int flag=0;//用于記錄是否有小數點出現
while((ch>47)&&(ch<58))//判斷當前的字符是否是數字
{
currentToken.name[k++]=ch;
ch=fgetc(sourceFile);
if(ch=='.')
{
flag=1;//出現了一個小數點,隨后進行是否為小數的判斷
currentToken.name[k++]=ch;
break;
}
}
if(flag==1)
{
ch=fgetc(sourceFile);
if((ch==',')||(ch==';'))//小數點后直接接了這兩個符號是違法的
{
printf("第%d行 %s : 非法數字\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
Token_Number++;
return;
}
while((ch>47)&&(ch<58))//讀入小數點后面的所有的字符
{
currentToken.name[k++]=ch;
ch=fgetc(sourceFile);
}
if((ch==',')||(ch==';'))//正確的數字遇到間隔符,表明是正確的數字
{
printf("第%d行 %s : 實常數\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=28,currentToken.name);
Token_Number++;
return;
}
if(ch=='.')//出現兩個小數點,后面緊接的所有符號作為違法的符號輸出
{
currentToken.name[k++]=ch;
while((ch!=' ')&&(ch!='\t')&&(ch!='\n')&&(ch!=';'))
{
ch=fgetc(sourceFile);
currentToken.name[k++]=ch;
}
printf("第%d行 %s : 這個數字中出現了兩個小數點!\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
Token_Number++;
return;
}
if(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//數字后面接了字母也為非法的數字
{
currentToken.name[k++]=ch;
ch=fgetc(sourceFile);
while(((ch>47)&&(ch<58))||((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//讀入所有的非法的字符
{
currentToken.name[k++]=ch;
ch=fgetc(sourceFile);
}
printf("第%d行 %s : 非法字符\n",row,currentToken.name);
fprintf(inFile,"%d %s %d\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
Token_Number++;
return;
}
}
else//可能是整型數字
{
if(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//數字后面跟了字母,屬于非法錯誤
{
currentToken.name[k++]=ch;
ch=fgetc(sourceFile);
while(((ch>47)&&(ch<58))||((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//讀入所有的非法的字母或數字
{
currentToken.name[k++]=ch;
ch=fgetc(sourceFile);
}
printf("第%d行 %s : 非法字符\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
Token_Number++;
return;
}
else//整形數字
{
printf("第%d行 %s : NUM\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=27,currentToken.name);
Token_Number++;
}
}
}
/************************字符或字符串的處理*****************************/
void IsAlpha()
{
int i=0,h=0;//h的作用與flag相似,用于判定讀入的字符串是否為關鍵字
while(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))//判定輸入的字符是否是字母
{
currentToken.name[i++]=ch;
ch=fgetc(sourceFile);
}
for(i=1;i<=6;i++)
{
h=strcmp(currentToken.name,symbleList[i].name);//與關鍵字進行比較
if(!h)
{
printf("第%d行 %s : 關鍵字\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=i,currentToken.name);
Token_Number++;
break;
}
}
if(h)
{
printf("第%d行 %s : ID\n",row,currentToken.name);//關鍵字以外的字符串全部定義為標識符
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=26,currentToken.name);
Token_Number++;
}
}
/****************************判定是否為注釋***********************/
//注釋的情況:遇到/*就進行判定,遇到*后判定下一個字符是否為/,是則是注釋,如果不是整個
//函數都將是錯誤的
void IsAnotation()
{
char ch1;
ch1=ch;
ch=fgetc(sourceFile);
if(ch=='*')
{
for(;;)
{
ch=fgetc(sourceFile);
if(ch==EOF)
{
printf("第%d行 沒有匹配的注釋符!\n",row);
break;
}
if(ch=='\n' )
{
row++; //行號加1
ch=fgetc(sourceFile);
}
if(ch=='*')
{
ch1=ch;
ch=fgetc(sourceFile);
if(ch=='/')
{
ch=fgetc(sourceFile);
break;
}
}
}
}
else
{
printf("第%d行 %c : 保留符\n",row,ch1);
currentToken.name[0]=ch1;
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=10,currentToken.name);
Token_Number++;
}
}
/***********************************判定是否為保留字***********************************/
void IsOther()
{
char ch1;
ch1=ch;
int i;
ch=fgetc(sourceFile);
for(i=0;i<30;i++)
currentToken.name[i]='\0';
switch(ch1)
{
case '+':currentToken.code=7;
currentToken.name[0]='+';
printf("第%d行 %c : 保留符\n",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
break;
case '-':currentToken.code=8;
currentToken.name[0]='-';
printf("第%d行 %c : 保留符\n",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
break;
case '*':currentToken.code=9;
currentToken.name[0]='*';
printf("第%d行 %c : 保留符\n",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
break;
case '/':currentToken.code=10;
currentToken.name[0]='/';
printf("第%d行 %c : 保留符\n",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
break;
case ',':currentToken.code=19;
currentToken.name[0]=',';
printf("第%d行 %c : 保留符\n",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
break;
case ';':currentToken.code=18;
currentToken.name[0]=';';
printf("第%d行 %c : 保留符\n",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
break;
case '<':if(ch=='=')
{
currentToken.code=12;
currentToken.name[0]='<';
currentToken.name[1]='=';
ch=fgetc(sourceFile);
}
else
{
currentToken.code=11;
currentToken.name[0]='<';
}
printf("第%d行 %s : 保留符",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
Token_Number++;
break;
case '>':if(ch=='=')
{
currentToken.code=14;
currentToken.name[0]='>';
currentToken.name[1]='=';
ch=fgetc(sourceFile);
}
else
{
currentToken.code=11;
currentToken.name[0]='>';
}
printf("第%d行 %s : 保留符",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
Token_Number++;
break;
case '=':if(ch=='=')
{
currentToken.code=15;
currentToken.name[0]='=';
currentToken.name[1]='=';
ch=fgetc(sourceFile);
}
else
{
currentToken.code=17;
currentToken.name[0]='=';
}
printf("第%d行 %s : 保留符\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
Token_Number++;
break;
case '!':if(ch=='=')
{
currentToken.code=16;
currentToken.name[0]='!';
currentToken.name[1]='=';
printf("第%d行 %c : 保留符\n",row,currentToken.name);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code,currentToken.name);
Token_Number++;
ch=fgetc(sourceFile);
}
else
{
printf("第%d行 此處為一個錯誤!\n",row);
fprintf(inFile,"%d %d %s\n",currentToken.LineofPro=row,currentToken.code=0,currentToken.name);
Token_Number++;
}
break;
case '(':currentToken.code=20;
currentToken.name[0]='(';
printf("第%d行 %c : 保留符",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
kuahao(ch1);
break;
case ')':currentToken.code=21;
currentToken.name[0]=')';
printf("第%d行 %c : 保留符",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
kuahao(ch1);
break;
case '[':currentToken.code=22;
currentToken.name[0]='[';
printf("第%d行 %c : 保留符",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
kuahao(ch1);
break;
case ']':currentToken.code=23;
currentToken.name[0]=']';
printf("第%d行 %c : 保留符",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
kuahao(ch1);
break;
case '{':currentToken.code=24;
currentToken.name[0]='{';
printf("第%d行 %c : 保留符",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
kuahao(ch1);
break;
case '}':currentToken.code=25;
currentToken.name[0]='}';
printf("第%d行 %c : 保留符",row,currentToken.name[0]);
fprintf(inFile,"%d %d %c\n",currentToken.LineofPro=row,currentToken.code,currentToken.name[0]);
Token_Number++;
kuahao(ch1);
break;
}
}
/************************************ 主函數*******************************************/
void main()
{
char filename[20];
int i,flag=0;
/**********************************初始化************************************/
if((keyFile=fopen("symble.txt","r"))==NULL)//打開關鍵字和保留字的文件,把他讀入到結構體數組中
{
printf("打不開文件symble.txt!\n");
exit(0);
}
if((inFile=fopen("token.txt","w"))==NULL)
{
printf("打不開文件token.txt!\n");
exit(0);
}
for(i=1;i<=29;i++)
fscanf(keyFile,"%d%s",&symbleList[i].code,symbleList[i].name);
printf(" *****************************************************************\n");
printf(" 詞法分析器\n");
printf(" *****************************************************************\n");
while(flag==0)
{
printf("請輸入您要分析的文件名稱:");
scanf("%s",filename);//sa.txt
if((sourceFile=fopen(filename,"r"))==NULL)
{
printf("無法打開文件!\n");
printf("請輸入正確的文件名!\n");
}
else
{
flag=1;
}
}
ch=fgetc(sourceFile);
for(i=0;i<20;i++)
parRight[i]='\0';
while(ch!=EOF)
{
if((ch==' ')||(ch=='\t'))
ch=fgetc(sourceFile);
if(ch=='\n')
{
ch=fgetc(sourceFile);
row++;//行號加1
}
for(i=0;i<30;i++)
currentToken.name[i]='\0';
if((ch>47)&&(ch<58))//是否為數字的判定
IsNumber();
else
if(((ch>64)&&(ch<91))||((ch>96)&&(ch<123)))
IsAlpha();//是否為字母或字符串的判定
else
if(ch=='/')//是否為注釋的判定
IsAnotation();
else
IsOther();//是否為保留字的判定
}
if(parRight[0]!='\0')//若所有程序都分析完成,數組中仍有括號沒有完成匹配,則程序的括號也是不匹配的
{
printf("您的程序的括號是不匹配的,請改正錯誤后在進行詞法分析!\n");
}
fclose(inFile);
printf("%d",Token_Number);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -