?? pl0.c
字號:
/*擴充了++a,--a,a++,a--,+=,-=,else語句,error錯誤說明*/
#include<stdio.h>
#include<stdlib.h>
#include"pl0.h"
#include"string.h"
/*解釋執行時使用的棧*/
#define stacksize 500
int main()
{
bool nxtlev[symnum];
system("cls");
printf("Input 1.txt to text 'else'\n");
printf("Input 2.txt to test '+= & -='\n");
printf("Input 3.txt to text '++'&'--'\n");
printf("Input 4.txt to text 'Error'\n");
printf("Input pl/0 file ?");
scanf("%s",fname); /*輸入文件名*/
fin=fopen(fname,"r");
if(fin)
{
printf("List object code ?(Y/N)"); /*是否輸出虛擬機代碼*/
scanf("%s",fname);
listswitch=(fname[0]=='y'||fname[0]=='Y');
printf("List symbol table ? (Y/N)"); /*是否輸出名字表*/
scanf("%s",fname);
tableswitch=(fname[0]=='y'||fname[0]=='Y');
fa1=fopen("fa1.tmp","w");
fprintf(fa1,"Iput pl/0 file ? ");
fprintf(fa1,"%s\n", fname);
init(); /*初始化*/
err=0;
cc=cx=ll=0;
ch=' ';
if(-1!=getsym())
{
fa=fopen("fa.tmp","w");
fas=fopen("fas.tmp","w");
addset(nxtlev,declbegsys,statbegsys,symnum);
nxtlev[period]=true;
if(-1==block(0,0,nxtlev)) /*調用編譯程序*/
{
fclose(fa);
fclose(fa1);
fclose(fas);
fclose(fin);
printf("\n");
return 0;
}
fclose(fa);
fclose(fa1);
fclose(fas);
if(sym!=period)
{
error(9);
}
if(err==0)
{
fa2=fopen("fa2.tmp", "w");
interpret();
fclose(fa2);
}
else
{
printf("Errors in pl/0 program");
}
}
fclose(fin);
}
else
{
printf("Can't open file! \n");
}
printf("\n");
return 0;
}
/*
*初始化
*/
void init()
{
int i;
for(i=0;i<=255;i++)
{
ssym[i]=nul;
}
ssym['+']=plus; /* char 的ASCI 作為數組下標*/
ssym['-']=minus;
ssym['*']=times;
ssym['/']=slash;
ssym['(']=lparen;
ssym[')']=rparen;
ssym['=']=eql;
ssym[',']=comma;
ssym['.']=period;
//ssym['#']=neq;
ssym[';']=semicolon;
/*設置保留字名字,按照字母順序,便于折半查找*/
strcpy(&(word[0][0]),"begin");
strcpy(&(word[1][0]),"call");
strcpy(&(word[2][0]),"const");
strcpy(&(word[3][0]),"do");
strcpy(&(word[5][0]),"else"); //擴
strcpy(&(word[6][0]),"end");
strcpy(&(word[8][0]),"if");
strcpy(&(word[9][0]),"odd");
strcpy(&(word[10][0]),"procedure");
strcpy(&(word[11][0]),"read");
strcpy(&(word[13][0]),"then");
strcpy(&(word[14][0]),"to");
strcpy(&(word[15][0]),"var");
strcpy(&(word[16][0]),"while");
strcpy(&(word[17][0]),"write");
/*設置保留字符號*/
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=constsym;
wsym[3]=dosym;
wsym[5]=elsesym; /* add else*/
wsym[6]=endsym;
wsym[8]=ifsym;
wsym[9]=oddsym;
wsym[10]=procsym;
wsym[11]=readsym;
wsym[13]=thensym;
wsym[14]=tosym; /*add tosym*/
wsym[15]=varsym;
wsym[16]=whilesym;
wsym[17]=writesym;
/*設置指令名稱*/
strcpy(&(mnemonic[lit][0]),"lit");
strcpy(&(mnemonic[opr][0]),"opr");
strcpy(&(mnemonic[lod][0]),"lod");
strcpy(&(mnemonic[sto][0]),"sto");
strcpy(&(mnemonic[cal][0]),"cal");
strcpy(&(mnemonic[inte][0]),"int");
strcpy(&(mnemonic[jmp][0]),"jmp");
strcpy(&(mnemonic[jpc][0]),"jpc");
/*設置符號集*/
for(i=0;i<symnum;i++)
{
declbegsys[i]=false;
statbegsys[i]=false;
facbegsys[i]=false;
}
/*設置聲明開始符號集*/
declbegsys[constsym]=true;
declbegsys[varsym]=true;
declbegsys[procsym]=true;
/*設置語句開始符號集*/
statbegsys[beginsym]=true;
statbegsys[callsym]=true;
statbegsys[ifsym]=true;
statbegsys[whilesym]=true;
/*設置因子開始符號集*/
facbegsys[ident]=true;
facbegsys[number]=true;
facbegsys[lparen]=true;
facbegsys[plusone]=true; // 添加前自加和前自減運算
facbegsys[minusone]=true;
}
/*
*用數組實現集合的集合運算
*/
int inset(int e,bool* s)
{
return s[e];
}
int addset(bool* sr,bool* s1,bool* s2,int n)
{
int i;
for(i=0;i<n;i++)
{
sr[i]=s1[i]||s2[i];
}
return 0;
}
int subset(bool* sr,bool* s1,bool* s2,int n)
{
int i;
for(i=0;i<n;i++)
{
sr[i]=s1[i]&&(!s2[i]);
}
return 0;
}
int mulset(bool* sr,bool* s1,bool* s2,int n)
{
int i;
for(i=0;i<n;i++)
{
sr[i]=s1[i]&&s2[i];
}
return 0;
}
/*
*出錯處理,打印出錯位置和錯誤編碼
*/
void error(int n)
{
char space[81];
memset(space,32,81);
space[cc-1]=0;//出錯時當前符號已經讀完,所以cc-1
printf("****%s!%d\n",space,n);
switch(n)
{
case 1:
printf("常數說明中的“=”寫成“:=”\n");
break;
case 2:
printf("常數說明中的“=”后應是數字\n");
break;
case 3:
printf("常數說明中的標識符應是“=”\n");
break;
case 4:
printf("const,var,procedure后應為標識符\n");
break;
case 5:
printf("漏掉了“,”或“;”\n");
break;
case 6:
printf("過程說明后的符號不正確\n");
break;
case 7:
printf("應是語句開始符\n");
break;
case 8:
printf("程序體內語句部分的后跟符不正確\n");
break;
case 9:
printf("程序結尾丟掉了“.”\n");
break;
case 10:
printf("語句之間漏掉了“;”\n");
break;
case 11:
printf("標識符未說明\n");
break;
case 12:
printf("賦值語句中,賦值號左部標識符屬性應是變量\n");
break;
case 13:
printf("賦值語句標識符后應是賦值號“:=”\n");
break;
case 14:
printf("call后應為標識符\n");
break;
case 15:
printf("call后標識符屬性應為過程\n");
break;
case 16:
printf("常數說明中的“=”寫成“:=”\n");
break;
case 17:
printf("丟了“end”或“;”\n");
break;
case 18:
printf("while型循環語句中丟了do\n");
break;
case 19:
printf("語句后的符號不正確\n");
break;
case 20:
printf("應為關系運算符\n");
break;
case 21:
printf("表達式內標識符屬性不能是過程\n");
break;
case 22:
printf("表達式中漏掉“)”\n");
break;
case 23:
printf("因子后的非法符號\n");
break;
case 24:
printf("表達式的開始符不能是此符號\n");
break;
case 31:
printf("數越界\n");
break;
case 32:
printf("read語句括號中的標識符不是變量\n");
break;
}
err++;
}
/*
* 漏掉空格,讀取一個字符
*
* 每次讀一行,存入line緩沖區,line被getsym取空后再讀一行
*
* 被函數getsym調用
*/
int getch()
{
if(cc==ll)
{
if(feof(fin))
{
printf("program incomplete");
return -1;
}
ll=0;
cc=0;
printf("%d ",cx );
fprintf(fa1,"%d ",cx);
ch=' ';
while(ch!=10)
{
//fscanf(fin,"%c",&ch)
if(EOF==fscanf(fin,"%c",&ch))
{
line[ll]=0;
break;
}
printf("%c",ch);
fprintf(fa1,"%c",ch);
line[ll]=ch;
ll++;
}
printf("\n");
fprintf(fa1,"\n");
}
ch=line[cc];
cc++;
return 0;
}
/*詞法分析,獲取一個符號
*/
int getsym()
{
int i,j,k;
while( ch==' '||ch==10||ch==9)
{
getchdo; /* 宏定義 getch*/
}
if(ch>='a'&&ch<='z')
{
k=0;
do{
if(k<al)
{
a[k]=ch; /*字符數組a為臨時符號*/
k++;
}
getchdo;
}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
a[k]=0;
strcpy(id,a);
i=0;
j=norw-1;
do{ /*折半查找保留字表*/
k=(i+j)/2;
if(strcmp(id,word[k])<=0)
{
j=k-1;
}
if(strcmp(id,word[k])>=0)
{
i=k+1;
}
}while(i<=j);
if(i-1>j) /* 找到,當前單詞為保留字*/
{
sym=wsym[k];
}
else /* 沒找到,為用戶定義的標識符*/
{
sym=ident;
}
}
else
{
if(ch>='0'&&ch<='9')
{
k=0;
num=0;
sym=number;
do{
num=10*num+ch-'0';
k++;
getchdo;
}while(ch>='0'&&ch<='9'); /*獲取數字的值*/
k--;
if(k>nmax)
{
error(30);
}
}
else
{
if(ch==':') /*檢測賦值符號*/
{
getchdo;
if(ch=='=')
{
sym=becomes; //becomes為:=
getchdo;
}
else
{
sym=nul; /*不能識別的符號*/
}
}
else
{
if(ch=='<') /*檢測小于或小于等于符號*/
{
getchdo;
if(ch=='=')
{
sym=leq; //leq為<=
getchdo;
}
else if(ch=='>') //add neq
{
sym=neq; //neq為<>
getchdo;
}
else
{
sym=lss; //lss為<
}
}
else// else 11 begin
{
if(ch=='>') /*檢測大于或大于等于符號*/
{
getchdo;
if(ch=='=')
{
sym=geq; //geq為>=
getchdo;
}
else
{
sym=gtr; //gtr為>
}
}
else
{
if(ch=='+') /*檢測+,+=,++符號*/
{
getchdo;
if(ch=='=')
{
sym=pluseq; //pluseq為+=
getchdo;
}
else if(ch=='+')
{
sym=plusone; //plusone為++
getchdo;
}
else
{
sym=plus; //plus為+
}
}
else
{
if(ch=='-') /*檢測-,-=,--符號*/
{
getchdo;
if(ch=='=')
{
sym=minuseq; //minuseq為-=
getchdo;
}
else if(ch=='-')
{
sym=minusone; //minusone為--
getchdo;
}
else
{
sym=minus; //minus為-
}
}
else
{
sym=ssym[ch];/* 當符號不滿足上述條件時,全部按照單字符號處理 包括“+”等*/
//getchdo;
//richard
if(sym!=period) /*檢測是否為程序終結*/
{
getchdo;
}
//end richard
}
}
}
}//else 11 end
}
}
}
return 0;
}
/*
*生成虛擬機代碼
*
*x:instruction.f;
*y:instruction.l;
*z:instruction.a;
*/
int gen(enum fct x,int y,int z)
{
if(cx>=cxmax)
{
printf("Program too long"); /*程序過長*/
return -1;
}
code[cx].f=x;
code[cx].l=y;
code[cx].a=z;
cx++;
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -