?? 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();/*當前過程有參數(shù)但沒有填寫過程表的就填寫*/
}
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();/*當前過程有參數(shù)但沒有填寫過程表的就填寫*/
}
processPL(fpread);//處理代碼過程,在lR分析階段這一過程是主要的過程
}
else
{
printf("\nERROR: line-> %d缺少關鍵字begin.",lineLocation);
skip(fpread);//錯誤處理
processShift(fpread,level);//程序再次轉移,看后續(xù)代碼的形式
}
break;
case 4://處理begin的過程
//printf("\nbegin.");
if(varLocation!=-1){
backPatch();/*當前過程有參數(shù)但沒有填寫過程表的就填寫*/
}
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();/*當前過程有參數(shù)但沒有填寫過程表的就填寫*/
}
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();/*當前過程有參數(shù)但沒有填寫過程表的就填寫*/
}
processPL(fpread);
}
else
{
printf("\nERROR: line-> %d缺少關鍵字begin.",lineLocation);
skip(fpread);
processShift(fpread,level);
}
break;
case 4://這是當子程序既沒有變量定義,又沒有子過程定義的時候的處理方法
//printf("\nbegin.");
if(varLocation!=-1){
backPatch();/*當前過程有參數(shù)但沒有填寫過程表的就填寫*/
}
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)//處理過程的參數(shù)定義,并將過程的部分信息填入過程表
{
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)//這個函數(shù)用于出錯的情況下跳過若干個字符,直到遇到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()//將過程定義的變量和參數(shù)信息填入過程表
{
process[curProcPtr-1].varCount=varcount;//過程中定義的變量個數(shù)
process[curProcPtr-1].varLocation=varLocation;//過程定義變量的開始位置(在變量表中的開始位置)
process[curProcPtr-1].totalCount=totalCount;//過程中定義的參數(shù)和變量的總個數(shù)
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;/*記錄第一個參數(shù)的位置*/
}
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 + -