📄 bianyi.cpp
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <malloc.h>
#include <conio.h>
#define g(x) (x-(x-65)*(x/(x-65+1)))%16
int line=1, row=1;
char KEY[8][6]={" ","BEGIN","THEN","DO","END","ELSE","IF","WHILE"}; //关键字表
int VAL[8]={17,1,4,7,2,5,3,6};//关键字对应种别号
int IsLetter(char ch) //判断是否是字母
{
if(isalpha(ch))
return 1;
return 0;
}
int IsDigit(char ch) //判断是否为数字
{
if(isalnum(ch))
return 1;
return 0;
}
int IsSpace(char ch) //判断是否为空白符(空格、换行、制表符等)
{
if(isspace(ch))
return 1;
return 0;
}
void GetChar(FILE *fp,char *ch) //读取字符送ch
{
*ch = fgetc(fp);
if(*ch=='\n')
{
line++;
row=1;
}
else row++;
}
void GetBC(FILE *fp,char *ch) //如果是空白则继续读下一个,直到不是空白
{
do{
GetChar(fp,ch);
}
while(IsSpace(*ch)&&(*ch != EOF));
}
void Retract(FILE *fp,char *ch) //光标回退一位,并使 ch 为空
{
fseek(fp,-1,1);
*ch = ' ';
row--;
}
int H(char key[]) //哈希函数:H(Key)=(L+g(key[1])+g(key[L]))%9
{
int L = strlen(key);
return (L+g(key[0])+g(key[L-1]))%9;
}
int Reserve(char *strToken) //返回关键字的编码(哈希函数法)
{
int h = H(strToken);
if(h > 8 || h < 0)
return 0;
if(strcmp(strToken, KEY[h]) == 0)
return h;
return 0;
}
void Concat(char *strToken, char *ch) //将ch中的字符连接到strToken后面
{
int i;
for(i=0;i<20;i++)
{
if(*strToken == NULL)
{
*strToken = *ch;
break;
}
strToken++;
}
}
void ErrorBranch(FILE *fp1,FILE *fp2) //出错处理分支程序
{
char ch;
printf("错误!非法字符!位于第%d行 第%d列\n", line, row-1);
fprintf(fp2,"错误!非法字符!位于第%d行 第%d列\n",line,row-1);
do{ //跳到下一个空白符
GetChar(fp1,&ch);
}
while(!IsSpace(ch)&&(ch != EOF));
}
int lexSubFunc(FILE *fp1,FILE *fp2) //词法分析子程序
{
char ch;
int i,code;
char strToken[255];
while(1)
{
GetBC(fp1,&ch);
for(i = 0;i < 255;i++)
strToken[i] = '\0';
if(ch == EOF)
return 0;
if(IsLetter(ch)) //标识符判断
{
while(IsLetter(ch)||IsDigit(ch))
{
Concat(strToken,&ch);
GetChar(fp1,&ch);
}
Retract(fp1,&ch);
code = Reserve(strToken);
if(code == 0)
{
printf("<17,\"%s\">\n",strToken);
fprintf(fp2,"<17,\"%s\">\n",strToken);
}
else
{
printf("<%d,\"%s\">\n",VAL[code],strToken);
fprintf(fp2,"<%d,\"%s\">\n",VAL[code],strToken);
}
}
else if(IsDigit(ch)) //整数判断
{
while (IsDigit(ch))
{
Concat(strToken,&ch);
GetChar(fp1,&ch);
}
Retract(fp1,&ch);
printf("<16,\"%s\">\n",strToken);
fprintf(fp2,"<16,\"%s\">\n",strToken);
}
else if (ch == '=') //其他符号判断
{
GetChar(fp1,&ch);
if(ch == '=')
{
printf("<12,\"==\">\n");
fputs("<12,\"==\">\n",fp2);
}
else
{
Retract(fp1,&ch);
printf("<8,\"=\">\n");
fputs("<8,\"=\">\n",fp2);
}
}
else if (ch == '+')
{
printf("<9,\"+\">\n");
fputs("<9,\"+\">\n",fp2);
}
else if (ch == '-')
{
printf("<10,\"-\">\n");
fputs("<10,\"-\">\n",fp2);
}
else if (ch == '<')
{
printf("<11,\"<\">\n");
fputs("<11,\"<\">\n",fp2);
}
else if (ch == '>')
{
printf("<13,\">\">\n");
fputs("<13,\">\">\n",fp2);
}
else if (ch == '.')
{
printf("<14,\".\">\n");
fputs("<14,\".\">\n",fp2);
}
else if (ch == ';')
{
printf("<15,\";\">\n");
fputs("<15,\";\">\n",fp2);
}
else if(ch =='/') //注释符号判断
{
GetChar(fp1,&ch);
if(ch =='/')
{
GetChar(fp1,&ch);
while(ch != '\n')
{
Concat(strToken,&ch);
GetChar(fp1,&ch);
}
printf("<18,\"//%s\">\n",strToken);
fprintf(fp2,"<18,\"//%s\">\n",strToken);
}
else
if(ch == '*')
{
GetBC(fp1,&ch);
while(ch !='*')
{
if(ch != '\n')
Concat(strToken,&ch);
GetBC(fp1,&ch);
}
GetChar(fp1,&ch);
if(ch =='/')
{
printf("<19,\" %s\">\n",strToken);
fprintf(fp2,"<19,\"%s\">\n",strToken);
}
}
else
ErrorBranch(fp1,fp2);
}
else
{ //非法字符处理
ErrorBranch(fp1,fp2);
}
}
}
void main()
{
FILE *fpin,*fpout;
if((fpin=fopen("sourse.txt","rt"))==NULL)
{
printf("无法打开文件 sourse.txt\n");
exit(1);
}
if((fpout=fopen("result.txt","wt+"))==NULL)
{
printf("无法创建文件 result.txt\n");
exit(1);
}
printf("\n输出结果为:\n");
lexSubFunc(fpin,fpout);
fclose(fpin);
fclose(fpout);
}
源程序sourse.txt:
BEGIN //程序开始
I=10;
J=I+5;
WHILE I= =10 DO /*当I=10时
执行循环*/
BEGIN ¥&
R=J+I;
I=I-1
END
END. //程序结束
输出单词二元式流文件result.txt:
<1,"BEGIN">
<18,"//程序开始">
<17,"I">
<8,"=">
<16,"10">
<15,";">
<17,"J">
<8,"=">
<17,"I">
<9,"+">
<16,"5">
<15,";">
<17,"WHILE">
<17,"I">
<8,"=">
<8,"=">
<16,"10">
<7,"DO">
<19,"当I=10时执行循环">
<1,"BEGIN">
错误!非法字符!位于第7行 第23列
<17,"R">
<8,"=">
<17,"J">
<9,"+">
<17,"I">
<15,";">
<17,"I">
<8,"=">
<17,"I">
<10,"-">
<16,"1">
<17,"END">
<17,"END">
<14,".">
<18,"//程序结束 ">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -