📄 grammer.cpp
字号:
#include <string.h>
#include "global.h"
#include "grammer.h"
void procProcess(FILE *fpread,int level)//递归的过程
{
struct record temp;
skipLine(fpread);//跳过换行符
fread(&temp,sizeof(struct record),1,fpread);//读一条记录,记录是二元式形式
if(((temp.kind==1)&&(level==0))||((temp.kind==3)&&(level>0)))
{
if(temp.kind==1)//这个单词是program
{
//printf("\nprogram.");
processProg(fpread,level);//处理program这一行程序
}
else if(temp.kind==3)//这个单词是procedure
{
//printf("\nprocedure.");
processProc(fpread,level);//处理procedure这一行程序
}
processShift(fpread,level);//程序转移处理
}
else
{
if(level==0)//如果处理的是主程序,主程序是第零层
{
printf("\nERROR: line-> %d 缺少program.",lineLocation); //输出错误信息
skip(fpread);//出错后就跳过若干个单词在处理
processShift(fpread,level);//程序转移处理
}
}
}
void processShift(FILE *fpread,int level)//按照程序的不同形式采取不同的处理方式,这是由于一些程序的模块可以有,也可以没有
{
struct record temp;
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);//读一个二元式,(词法分析的结果)
switch(temp.kind)//查看读出的单词的编码,按照编码决定程序的走向
{
case 2://处理var定义变量,这是处理变量定义的过程
do
{
//printf("\nvar.");
processVariable(fpread,level);//处理变量,将变量填入符号表
skipLine(fpread);//跳过换行符,增加了程序的灵活性,一行代码可以写在若干行
fread(&temp,sizeof(struct record),1,fpread);//读一条记录
}while(temp.kind==2);//如果有多条定义变量的语句
switch(temp.kind)
{
case 3://处理过程procedure定义
do
{
//printf("\nprocedure.");
fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
if(varLocation!=-1){
backPatch();/*当前过程有参数但没有填写过程表的就填写*/
}
procProcess(fpread,level+1);//递归调用,处理过程
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
}while(temp.kind==3);//如果有多个过程定义
if(temp.kind==4)//处理begin-end这段代码过程
{
//printf("\nbegin.");
if(varLocation!=-1){
backPatch();/*当前过程有参数但没有填写过程表的就填写*/
}
processPL(fpread);//处理代码过程,在lR分析阶段这一过程是主要的过程
}
else
{
printf("\nERROR: line-> %d缺少关键字begin.",lineLocation);
skip(fpread);//错误处理
processShift(fpread,level);//程序再次转移,看后续代码的形式
}
break;
case 4://处理begin的过程
//printf("\nbegin.");
if(varLocation!=-1){
backPatch();/*当前过程有参数但没有填写过程表的就填写*/
}
processPL(fpread);
break;
case 17://定义的是变量(17是标识符的编码)
printf("\nERROR: line-> %d缺少关键字var或procedure.",lineLocation);
skip(fpread);
processShift(fpread,level);
break;
default://出错了,这是出错的处理
printf("\nERROR: line-> %d",lineLocation);
skip(fpread);
processShift(fpread,level);//转移处理
break;
}
break;
case 3://这是在一个过程中没有变量定义的时候的处理的情况,有些子程序可以没有变量定义
do
{
//printf("\nprocedure.");
fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
if(varLocation!=-1){
backPatch();/*当前过程有参数但没有填写过程表的就填写*/
}
procProcess(fpread,level+1);
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
}
while(temp.kind==3);
if(temp.kind==4)
{
//printf("\nbegin.");
if(varLocation!=-1){
backPatch();/*当前过程有参数但没有填写过程表的就填写*/
}
processPL(fpread);
}
else
{
printf("\nERROR: line-> %d缺少关键字begin.",lineLocation);
skip(fpread);
processShift(fpread,level);
}
break;
case 4://这是当子程序既没有变量定义,又没有子过程定义的时候的处理方法
//printf("\nbegin.");
if(varLocation!=-1){
backPatch();/*当前过程有参数但没有填写过程表的就填写*/
}
processPL(fpread);
break;
case 17:
printf("\nERROR: line-> %d缺少关键字var或procedure.",lineLocation);
skip(fpread);
processShift(fpread,level);
break;
default:
printf("\nERROR: line-> %d",lineLocation);
skip(fpread);
processShift(fpread,level);
break;
}
}
void processPL(FILE *fpread)//这个过程不处理具体的代码,代码的分析有LR语法分析阶段完成
{
struct record temp;
while(!feof(fpread)){
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==35){
lineLocation++;
}else if(temp.kind==5){
//printf("\nend.");
return;
}
}
if(temp.kind!=5)
{
printf("\nERROR:程序缺少END.");
}
if(temp.kind!=34)
{
printf("\nERROR:整个程序缺少终结符\".\"");
}
}
void processVariable(FILE *fpread,int level)//处理变量的过程,包括判断变量是否重定义和将变量填入符号表
{
struct record temp;
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
while(temp.kind==17)//判断读入的是否变量,变量的编码是17
{
//printf("\n%s",temp.strName);
totalCount++;
enterVarTable(temp.strName,level,totalCount);
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==33)
{
//printf("\n;");
return;
}
else if(temp.kind==32)
{
//printf("\n,");
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
}
else if((temp.kind!=32)&&(temp.kind!=33))
{
skip(fpread);
printf("\nERROR: line-> %d缺少结束符",lineLocation);
}
}
}
void processProc(FILE *fpread,int level)//处理过程的定义
{
struct record temp;
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==17)
{
//printf("\n%s.",temp.strName);
enterProcTable(temp.strName,level,level-1);
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==30)
{
//printf("\n(.");
processID(fpread,level);
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==31)
{
//printf("\n).");
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind!=33)
{
skip(fpread);
printf("\nERROR: line->%d缺少结束符",lineLocation);
}
}
else
{
skip(fpread);
printf("\nERROR: line->%d缺少右括号",lineLocation);
}
}
else if(temp.kind!=33)
{
skip(fpread);
printf("\nERROR: line->%d缺少结束符分号",lineLocation);
}
}
else
{
printf("\nERROR: line->%d主程序没有定义名字",lineLocation);
skip(fpread);
return;
}
}
void processID(FILE *fpread,int level)//处理过程的参数定义,并将过程的部分信息填入过程表
{
struct record temp;
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
while(temp.kind==17)
{
//printf("\n%s.",temp.strName);
totalCount++;
varcount++;
enterVarTable(temp.strName,level,totalCount);
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==31)
{
//printf("\n).");
fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
return;
}
else if(temp.kind==32)
{
//printf("\n,.");
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
}
else if((temp.kind!=32)&&(temp.kind!=31))
{
skip(fpread);
printf("\nERROR: line->%d缺少右括号",lineLocation);
}
}
}
void processProg(FILE *fpread,int level)//专门处理program开头的这条语句,也就是分析程序的开头
{
struct record temp;
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==17)
{
//printf("\n%s.",temp.strName);
enterProcTable(temp.strName,level,level-1);
skipLine(fpread);
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind!=33)
{
printf("\nERROR: line-> %d缺少分号",lineLocation);
skip(fpread);
return;
}
}
else
{
printf("\nERROR: line-> %d主程序没有定义名字",lineLocation);
skip(fpread);
return;
}
}
void skip(FILE *fpread)//这个函数用于出错的情况下跳过若干个字符,直到遇到var,procedure,begin为止
{
struct record temp;
while(!feof(fpread)){
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==35){
lineLocation++;
}else if((temp.kind==2)||(temp.kind==3)||(temp.kind==4)){
fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
return;
}
}
}
void skipLine(FILE *fpread)/*跳过换行符*/
{
struct record temp;
while(!feof(fpread)){
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==35){
lineLocation++;
}else{
fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
break;
}
}
}
int searchprocTable(char procName[])//查找是否有同名的过程
{
int i=0;
if(curProcPtr==0)//过程表中没内容
return 0;
else//过程表中有内容,开始查找制定过程
{
for(i=0;i<curProcPtr;i++)
{
if(!(strcmp(process[i].procName,procName)))
return 1;//找到同名过程,返回1
}
return 0;//没有找到同名过程返回0
}
}
void enterProcTable(char procName[],int level,int exProc)//将过程中定义的过程名填入过程表
{
if(searchprocTable(procName))//查找是否有同名的过程
{
printf("\nERROR:procedure %s has been defined.",procName);
}
else//没有同名的过程就将该过程名填入过程表
{
strcpy(process[curProcPtr].procName,procName);//填入过程的名字
process[curProcPtr].level=level;//填入过程的层次
process[curProcPtr].exProc=exProc; //填入该过程的外过程
curProcPtr++;//过程表的指针加1
}
}
void backPatch()//将过程定义的变量和参数信息填入过程表
{
process[curProcPtr-1].varCount=varcount;//过程中定义的变量个数
process[curProcPtr-1].varLocation=varLocation;//过程定义变量的开始位置(在变量表中的开始位置)
process[curProcPtr-1].totalCount=totalCount;//过程中定义的参数和变量的总个数
totalCount=0;
varcount=0;
varLocation=-1;
}
int searchVarTable(char varName[])//在变量表中查找变量
{
int i=0;
if(curVarPtr==0)//变量标中没内容返回0
return 0;
else//变量表中有内容,则开始查找改变量
{
for(i=0;i<curVarPtr;i++)
{
if(!(strcmp(variable[i].varName,varName)))
return 1;//找到制定变量就返回1
}
return 0;//没有找到变量就返回0
}
}
void enterVarTable(char varName[],int level,int relative)//将变量填入变量表
{
if(searchVarTable(varName))//察看变量是否在变量表中存在,也就是看变量是否重定义
{
printf("\nERROR: variable %s has been defined.",varName);
}
else//如果变量以前没有定义,就将他填入变量表中
{
strcpy(variable[curVarPtr].varName,varName);
variable[curVarPtr].level=level;
variable[curVarPtr].relative=relative;
if(varLocation==-1)
{
varLocation=curVarPtr;/*记录第一个参数的位置*/
}
curVarPtr++;
}
}
void displayVarTable()//将变量标的内容在屏幕上显示出来,方便调试以及测试程序运行是否正确
{
int i=0;
printf("\nvarName: level: relative:\n");
for(i=0;i<curVarPtr;i++)
{
printf("%-20s",variable[i].varName);
printf("%-10d",variable[i].level);
printf("%-10d",variable[i].relative);
printf("\n");
}
}
void displayProcTable()//将过程表的内容在屏幕上显示出来
{
int i=0;
printf("\nprocName: level: varCount: varLocation: exProc: totalCount:\n");
for(i=0;i<curProcPtr;i++)
{
printf("%-20s",process[i].procName);
printf("%-8d",process[i].level);
printf("%-10d",process[i].varCount);
printf("%-15d",process[i].varLocation);
printf("%-8d",process[i].exProc);
printf("%-12d",process[i].totalCount);
printf("\n");
}
}
void ishaveLast(FILE *fpread)
{
struct record temp;
while(!feof(fpread)){
fread(&temp,sizeof(struct record),1,fpread);
if(temp.kind==35){
lineLocation++;
}else if(temp.kind==34){
return;
}
}
if(temp.kind!=34)
{
printf("\nERROR:整个程序缺少终结符\".\"");
}
}
int main()
{
FILE *fpread;
if((fpread=fopen("out.pbj","rb"))==NULL)
{
printf("\n没有词法分析器产生的中间文件.\n");
// exit(0);
}
procProcess(fpread,0);//分析过程开始
ishaveLast(fpread);
fclose(fpread);
displayVarTable();//输出变量表
displayProcTable();//输出过程表
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -