📄 accidanaly.c
字号:
#include "AccidAnaly.h"
////////////////////////////// 以下是主模块 /////////////////////////////////
void main(void)
{
char temp='a';
InitAll(); //初始化
//-------------------------------------------------------------------------//
printf("\n 您需要改变data.c文件中的源程序吗(Y/N):");
while ((temp != 'Y')&&(temp != 'y')&&
(temp != 'N')&&(temp != 'n'))
{
temp = getchar();
getchar();
}
if ( (temp=='y') || (temp=='Y') )
{
printf("\n 请输入您的源程序:\n");
if ( !InputData() )
exit(1);
}
temp='a';
//-------------------------------------------------------------------------//
while ( !AccidAnaly() )
{
printf("\n 您的输入不正确,请检查并再次输入您的源程序:\n");
if ( !InputData() )
exit(1);
}
//-------------------------------------------------------------------------//
printf("\n 您需要输出TwoElem.c文件中的二元式吗(Y/N):");
while ((temp != 'Y')&&(temp != 'y')&&
(temp != 'N')&&(temp != 'n'))
{
temp = getchar();
getchar();
}
if ( (temp=='y') || (temp=='Y') )
{
PrintTElem();
}
temp='a';
//--------------------------------------------------------------------------//
printf("\n 您需要输出SymTable.c文件中的符号表吗(Y/N):");
while ((temp != 'Y')&&(temp != 'y')&&
(temp != 'N')&&(temp != 'n'))
{
temp = getchar();
getchar();
}
if ( (temp=='y') || (temp=='Y') )
{
PrintTable();
}
//--------------------------------------------------------------------------//
printf("\n 源程序分析结束,谢谢使用!\n");
}
void InitAll(void)
{
int i=0;
//设置单字符符号
for (i=0; i<=255; i++)
{
OBSym[i] = nul;
}
OBSym['+'] = plus;
OBSym['-'] = minus;
OBSym['*'] = times;
OBSym['/'] = slash;
OBSym['('] = lparen;
OBSym[')'] = rparen;
OBSym['='] = eql;
OBSym[','] = comma;
OBSym[';'] = semicolon;
OBSym['.'] = period;
//清空扫描缓冲区
for (i=0; i<SCANBUFF; i++)
{
scanbuffer[i] = '\0';
}
//清空符号表
for (i=0; i<MAXSYMTAB; i++)
{
table[i].name[0] = '\0';
}
}
///////////////////////////////以下是源程序输入模块//////////////////////////////////
///////////////////////功能:把从键盘输入程序代码存入文件data.c中。////////////////////
///////////////////////正常结束则返回TURE,非正常结束则返回ERROR。////////////////////
int InputData(void)
{
char buffer[120];
if ( !(fp_data=fopen("data.c", "wb")) ) //打开文件
{
printf ("cannot open file!");
return ERROR;
}
while (1)
{
gets( buffer ); //从键盘接收字符串
if ( !buffer[0] ) break; //判断输入是否结束
fputc('\n', fp_data); //在文件中输入换行符
fputs(buffer, fp_data); //将字符串输入文件
}
fclose(fp_data);
return OK;
}
/////////////////////////////////////以下是词法分析模块///////////////////////////////////
////////////功能:从文件Data.c中读取源程序,经词法分析器分析后产生用二元式表示的单词符号串。
///////////将该二元式序列存入文件TwoElem.c中。词法分析器在一边读取数据时,要一边填写符号表。
///////将符号表存入文件SymTable.c中。并根据用户的要求,决定是否输出TwoElem和SymTable中的值。
//////返回值为TURE表示源程序经分析后没错,若为ERROR则表示源程序有错,并打印错误类型和行号
int AccidAnaly(void)
{
int ErrorNum=0; //错误类型号
int ErrorFlag=TRUE; //错误标识 OK表示无错,ERROR表示有错
//-------------------------------------------------------------------
if (!(fp_data=fopen("data.c", "rb"))) //打开文件data.c
{
printf ("cannot open file!");
return ERROR;
}
fgetc(fp_data); //过滤掉第一个换行符
//-------------------------------------------------------------------
if (!(fp_TwoElem=fopen("TwoElem.c", "wb"))) //打开文件TwoElem.c
{
printf ("cannot open file!");
return ERROR;
}
//-------------------------------------------------------------------
while ( ErrorNum=GetSym() )
{
if ( !(Error(ErrorNum)) ) //如果单词符号获取有错,则调用出错处理程序
{
ErrorFlag = ERROR;
}
if ( ErrorNum==4 ) //无结束符.
{
return ERROR;
}
ch =' ';
}
//-------------------------------------------------------------------
fclose(fp_data); //关闭源程序文件
fclose(fp_TwoElem); //关闭二元式文件
return ErrorFlag;
}
int GetSym(void)
{
//获得一个单词符号,返回值为0表示源程序分析结束,为1表示没错,>1表示出错类型号
int ErrorNum=TRUE;
while ( ch==' ')
{
ErrorNum = Getch(); //获得一个非空字符
if (ErrorNum!=OK)
return ErrorNum;
}
if ( (('A'<=ch)&&(ch<='Z')) || (('a'<=ch)&&(ch<='z')) )
{
ErrorNum = state_CharStr(); //进入基本字标识符处理状态
ch = ' ';
}
else if ( ('0'<=ch)&&(ch<='9') )
{
ErrorNum = state_Number(); //进入常数处理状态
}
else if ( (ch=='+') || (ch=='-') || (ch=='*') || (ch=='/') || (ch=='=') ||
(ch==':') || (ch=='(') || (ch==')') || (ch==',') || (ch==';') || (ch=='.'))
{
ErrorNum = state_OptBoud(); //进入运算符界符处理状态
}
else if ( ch==' ' )
{
}
else
{
ErrorNum = 5; //否则置出错类型号5
}
return ErrorNum;
}
int Getch(void)
{
//从扫描缓冲区中获得一个非空字符,返回值为OK表示正常返回,否则为错误类型号
if ( scanbuffer[start] == '\n' || scanbuffer[start] == '\0')
{
if ( feof(fp_data) )
{
printf("\n 文件已空!");
return 4; //错误类型号4,无结束符号
}
else
{
fgets(scanbuffer, 120, fp_data); //从文件fp_data中读取一行字符到扫描缓冲区
line++; //行数增一
start = 0; //置扫描指针
}
}
else
{
ch = scanbuffer[start];
start++;
}
return OK;
}
int state_CharStr() //基本字和标示符处理
{
int i=0;
int Adr=0;
int error=OK;
token[i++] = ch;
while ( (('A'<=scanbuffer[start])&&(scanbuffer[start]<='Z')) ||
(('a'<=scanbuffer[start])&&(scanbuffer[start]<='z')) ||
(('0'<=scanbuffer[start])&&(scanbuffer[start]<='9')) )
{
if ( i<MAXSYMNUM )
{
token[i++] = scanbuffer[start++];
}
else
{
start++;
}
}
token[i] = '\0';
for (i=0; i<KEYWORDS; i++) //判断是否为关键字
{
if ( !(strcmp(KeyWord[i], token)) ) break;
}
if ( i<KEYWORDS )
{
BackUp = KwSym[i];
SaveTElem( KwSym[i], 0 );
}
else
{
error = LoadTable( &Adr );
if ( OK == error )
{
SaveTElem( ident, Adr );
}
else
{
//Error( error );
return ERROR;
}
}
return OK;
}
int state_Number() //常数处理
{
int i=0;
int error=OK;
int Adr=0;
token[i++] = ch;
while ( ('0'<=scanbuffer[start])&&(scanbuffer[start]<='9') )
{
if ( i<4 )
{
token[i++] = scanbuffer[start++];
}
else
{
while ( ('0'<=scanbuffer[start])&&(scanbuffer[start]<='9') ) //跳过该字符
{
start++;
}
return 3; //错误类型号3,越界
}
}
token[i] = '\0';
Num = IntegerConversion(0, --i);
error = LoadTable( &Adr );
if ( OK == error )
{
SaveTElem( number, Adr );
}
else
{
// Error( error );
return ERROR;
}
return OK;
}
int IntegerConversion(int begine, int end) //整数转换
{
int i;
int temp=0;
int integer=0;
for(i=begine; i<=end; i++)
{
temp = token[i] - 48;
integer = integer*10 +temp;
}
return integer;
}
int state_OptBoud() //运算符界符处理
{
if ( (ch=='+') || (ch=='-') || (ch=='*') || (ch=='/') || (ch=='=') ||
(ch=='(') || (ch==')') || (ch==',') || (ch==';') )
{
SaveTElem( OBSym[ch], 0);
// if (ch==';') BackUp = nul;
}
else if (ch==':')
{
if ( scanbuffer[start] != '=' )
{
return 2; //错误类型号2
}
else
{
start++;
SaveTElem( evaluate, 0 );
}
}
else //.
{
return 0;
}
return OK;
}
int SaveTElem(enum Symbol Sym, int adr) //将二元式存入文件TwoElem.c中
{
TElem telem;
// printf("\n%d, %d", Sym, adr);
telem.category = Sym;
telem.adr = adr;
fwrite(&telem, sizeof(TElem), 1, fp_TwoElem);
return OK;
}
int Error(int ErrorNum) //出错处理函数
{
switch (ErrorNum)
{
case OK:
return OK;
break;
case 2:
printf("\n第%d行的赋值运算符错误!", line);
break;
case 3:
printf("\n第%d行的数值越界!", line);
break;
case 4:
printf("\n源程序没有结束符号!", line);
break;
case 5:
printf("\n第%d行引入了非法字符!", line);
break;
case 6:
printf("\n第%d行的某一标识符不能识别!", line);
break;
case 7:
printf("\n源程序中已经存在该过程名!");
break;
case 8:
printf("\n源程序中存在不可知错误!");
break;
default:
break;
}
return ERROR;
}
void PrintTElem(void) //打印二元式序列
{
TElem telem;
if ( !(fp_TwoElem=fopen("TwoElem.c", "rb")) ) //打开文件
{
printf ("cannot open file!");
}
while ( !feof(fp_TwoElem) )
{
fread(&telem, sizeof(TElem), 1, fp_TwoElem);
printf("\n%d, %d", telem.category , telem.adr);
}
fclose(fp_TwoElem);
}
int LoadTable(int* AAdr) //登录符号表
{
//如果登录成功则返回OK,否则返回错误类型号
if (BackUp == nul)
{
return 6;
}
else if ( (BackUp == constsym) || (token[0]>='0' && token[0]<='9')) //常量处理
{
return ( DealConst(AAdr) );
}
// else if (BackUp == varsym) //变量处理
// {
// return ( DealVar(AAdr) );
// }
else if (BackUp == procsym) //变量处理
{
return ( DealProc(AAdr) );
}
// else
// {
// return 8;
// }
else
{
return ( DealVar(AAdr) );
}
}
int DealConst(int* AAdr)
{
//参数AAdr所指的单元内容作常量在符号表的地址返回,返回值OK表示正常结束,否则为出错类型号
if ( token[0]>='0' && token[0]<='9' )
{
table[backp].value = Num ;
}
else
{
strcpy(table[backp].name, token);
table[backp].kind = constsym;
Ptable++;
}
table[backp].Adr = 0;
table[backp].level = 0;
*AAdr = backp;
return OK;
}
int DealVar(int* AAdr)
{
//参数AAdr所指的单元内容作变量在符号表的地址返回,返回值OK表示正常结束,否则为出错类型号
int i=0;
for (i=0; i<Ptable; i++)
{
if ( !strcmp(table[i].name, token) ) break;
}
if ( i<Ptable )
{
backp = i;
*AAdr = backp;
}
else
{
table[Ptable].kind = varsym;
table[Ptable].level = level;
strcpy(table[Ptable].name, token);
table[Ptable].value = 0;
*AAdr = Ptable;
backp = Ptable++;
}
return OK;
}
int DealProc(int* AAdr)
{
//参数AAdr所指的单元内容作过程名在符号表的地址返回,返回值OK表示正常结束,否则为出错类型号
int i=0;
for (i=0; i<Ptable; i++)
{
if ( !strcmp(table[i].name, token) ) break;
}
if ( i<Ptable )
{
return 7;
}
else
{
table[Ptable].kind = procsym;
table[Ptable].level = level;
strcpy(table[Ptable].name, token);
table[Ptable].size = 5;
level++;
*AAdr = Ptable;
backp = ++Ptable;
}
return OK;
}
void PrintTable(void) //打印符号表
{
int i=0;
for (i=1; i<Ptable; i++)
{
puts( table[i].name );
printf( " %d %d %d %d %d \n", table[i].kind, table[i].value, table[i].level, table[i].Adr,table[i].size);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -