?? pl0.cpp
字號:
#include "pl0.h"
/**************************************************************************
* PL/0 語言編譯程序,由江漢石油學院計算機系周云才根據清華大學出版社出版,
* 呂映芝,張素琴,蔣維杜編寫的教材《編譯原理》中第二章(PL/0編譯程序的實現)
* 以及附錄A中的代碼改編而成。
* 代碼版權由周云才擁有,使用者必須遵循以下約定:
* 可以免費使用此文件,但必須包含此聲明。
* 可以修改、傳播、打印、出版這里的源代碼。
* 可以在任何軟件工程中使用這里的源代碼。
* 周云才對于由此源代碼的使用而引起的任何問題沒有任何責任。
* 周云才地址:湖北省荊州市江漢石油學院計算機系
* 郵編:434023
* 信箱:zyc262@163.net
* 電話: 0716-8431262
**********************************************************************************************/
string PL0::errStr[]={" ","error 0001: 常數說明中“=”寫成“:=”",
"error 0002: 常數說明中的“=”后應為數字",
"error 0003: 常數說明中的標識符后應是“=”",
"error 0004: const,var,procedure后應為標識符",
"error 0005: 漏掉了‘,’或‘;’",
"error 0006: 過程說明后的符號不正確(應是語句開始符或過程開始符)",
"error 0007: 應是語句開始符",
"error 0008: 過程體內語句部分的后跟符不正確",
"error 0009: 程序皆為丟了句號‘.’",
"error 0010: 語句之間漏了‘;’",
"error 0011: 標識符沒說明",
"error 0012: 賦值語句中,賦值號左部標識符屬性應是變量",
"error 0013: 賦值語句左部標識符應是賦值號:=",
"error 0014: call后應為標識符",
"error 0015: call后標識符屬性應為過程",
"error 0016: 條件語句中丟了then",
"error 0017: 丟了end或;",
"error 0018: while型循環語句中丟了do",
"error 0019: 語句后的標識符不正確",
"error 0020: 應為關系運算符",
"error 0021: 表達式內標識符屬性不能是過程",
"error 0022: 表達式中漏掉了右括號‘)’",
"error 0023: 因子后的非法符號",
"error 0024: 表達式開始符不能是此符號",
"error 0025: 文件在不該結束的地方結束了",
"error 0026: 結束符出現在不該結束的地方",
"error 0027: ","error 0028: ","error 0029: ","error 0030: ",
"error 0031: 數越界",
"error 0032: read語句括號中標識符不是變量"};
PL0::PL0(char* source,char*destination)
{
listswitch=true,sourceEnd=false;
strcpy(word[1],"begin");
strcpy(word[2],"call");
strcpy(word[3],"const");
strcpy(word[4],"do");
strcpy(word[5],"end");
strcpy(word[6],"if");
strcpy(word[7],"odd");
strcpy(word[8],"procedure");
strcpy(word[9],"read");
strcpy(word[10],"then");
strcpy(word[11],"var");
strcpy(word[12],"while");
strcpy(word[13],"write");
wsym[1]= BEGINSYM; wsym[2]=CALLSYM;
wsym[3]= CONSTSYM; wsym[4]=DOSYM;
wsym[5]=ENDSYM; wsym[6]=IFSYM;
wsym[7]=ODDSYM; wsym[8]=PROCSYM;
wsym[9]=READSYM; wsym[10]=THENSYM;
wsym[11]=VARSYM; wsym[12]=WHILESYM;
wsym[13]=WRITESYM;
memset(code,0,sizeof(code));
memset(ssym,0,100*sizeof(symbol));
memset(table,0,sizeof(table));
memset(line,0,sizeof(line));
ssym['+']= PLUS;
ssym['-']= MINUS;
ssym['*']= TIMES;
ssym['/']= SLASH;
ssym['(']= LPAREN;
ssym[')']= RPAREN;
ssym['=']= EQL;
ssym[',']= COMMA;
ssym['.']= PERIOD;
ssym['#']= NEQ;
ssym['<']= LSS;
ssym['>']= GTR;
ssym[';']= SEMICOLON;
strcpy(mnemonic[LIT]," lit ");
strcpy(mnemonic[OPR]," opr ");
strcpy(mnemonic[LOD]," lod ");
strcpy(mnemonic[STO]," sto ");
strcpy(mnemonic[CAL]," cal ");
strcpy(mnemonic[INT]," int ");
strcpy(mnemonic[JMP]," jmp ");
strcpy(mnemonic[JPC]," jpc ");
declbegsys.insert(CONSTSYM),declbegsys.insert(VARSYM),declbegsys.insert(PROCSYM);
statbegsys.insert(BEGINSYM),statbegsys.insert(CALLSYM),statbegsys.insert(IFSYM),statbegsys.insert(WHILESYM);
facbegsys.insert(IDENT),facbegsys.insert(NUMBER),facbegsys.insert(LPAREN);
err= 0;
cc= 0;
cx= 0;
ll= 0;
ch= ' ';
kk= al;
codeNo=0;
fin=fopen(source,"r");
fout=fopen(destination,"w");
}
void PL0::error(int n)
{
char s[10];
sprintf(s,"第 %d 行:",codeNo);
errorString.push_back(s+errStr[n]);
err= err+1;//error count
}//error end
void PL0::getch()
{
if(cc==ll)
{
if(feof(fin))
{
if(sym!=PERIOD)
error(25);
sourceEnd=true;
return;
}
cc= 0;
fgets(line,lineLength,fin);
codeNo++;
ll=strlen(line);
if(line[ll-1]==10)ll--;
}
ch= line[cc];
cc= cc+1;
}
void PL0::getsym()
{
if(sourceEnd)
return;
int i,j,k;
while (ch ==' '||ch==9)
getch();//cls space and tab
if(isalpha(ch))//id or reserved word
{
k=0;
memset(a,0,al+1);
do{
if (k < al)
{
a[k]= ch;
k= k+1;
}
getch();
if(sourceEnd)
return;
}while(isalpha(ch)||isdigit(ch));
if(k >= kk)
kk= k;
else
{
do{
a[kk]= ' ';
kk= kk-1;
}while(kk > k);
}
strcpy(id,a);
i= 1;
j= norw;
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(isdigit(ch))//number
{
k= 0;
num= 0;
sym= NUMBER;
do{
num= 10 * num+ch-'0';
k= k+1;
getch();
}while(isdigit(ch));
if(k > nmax)
error(30);
}
else if (ch == ':')
{
getch();
if( ch== '=')
{
sym= BECOMES;
getch();
}
else
sym= NUL;
}
else if(ch == '<')//extra stuff added to support <=
{
getch();
if (ch== '=')
{
sym= LEQ;
getch();
}
else
sym= LSS;
}
else if (ch == '>')
{
getch();
if( ch == '=')
{
sym= GEQ;
getch();
}
else
sym= GTR;
}
else//end of extra stuff
{
sym= ssym[ch];
getch();
}
}
void PL0::gen(fct x,int y,int z)
{
if (cx > cxmax)
{
cout<<"Program too long\n";
return;
}
code[cx].f= x;
code[cx].l= y;
code[cx].a= z;
cx= cx+1;
}//gen end
void PL0::test(symset s1,symset s2,int n)
{
if(sourceEnd)return;
if (s1.find(sym)==s1.end())
{
error(n);
symset::iterator it;
for(it=s2.begin();it!=s2.end();it++)
s1.insert(*it);//s1=s1+s2
while (s1.find(sym)==s1.end())
getsym();
}
}//test end
void PL0::enter(obj0 k,int &tx,int &dx,int lev)
{
tx= tx+1;
strcpy(table[tx].name,id);
table[tx].kind=k;
switch(k)
{
case CONSTANT:
if(num>amax)
{
error(31);
num=0;
}
table[tx].other.val=num;
break;
case VARIABLE:
table[tx].other.inOther.level=lev;
table[tx].other.inOther.adr=dx;
dx++;
break;
case PROCEDURE:
table[tx].other.inOther.level=lev;
break;
}
}//enter end
int PL0::position(alfa id,int tx)//find identifier id in table
{
int i;
strcpy(table[0].name, id);
i= tx;
while (strcmp(table[i].name,id)!=0)i--;
return i;
}//position end
void PL0::constdeclaration(int&tx,int&dx,int lev)
{
if(sym = IDENT)
{
getsym();
if(sym>=EQL&&sym<=BECOMES)
{
if( sym ==BECOMES)
error(1);
getsym();
if( sym == NUMBER)
{
enter(CONSTANT,tx,dx,lev);
getsym();
}
else
error(2);
}
else
error(3);
}
else
error(4);
}// constdeclaration end
void PL0::vardeclaration(int&tx,int&dx,int lev)
{
if( sym == IDENT)
{
enter(VARIABLE,tx,dx,lev);
getsym();
}
else
error(4);
}//vardeclaration end
void PL0::listcode(int cx0)//list code generated for this block
{
int i;
if(listswitch)
for (i= cx0;i<cx;i++)
cout<<" "<<i<<" "<<mnemonic[code[i].f]
<<" "<<code[i].l<<" "<<code[i].a<<endl;
}// listcode end
void PL0:: factor(symset fsys,int tx,int lev)
{
int i;
test(facbegsys,fsys,24);
while(facbegsys.find(sym)!=facbegsys.end())
{
if( sym ==IDENT)
{
i= position(id,tx);
if( i == 0)
error(11);
else
switch(table[i].kind)
{
case CONSTANT:
gen(LIT,0,table[i].other.val);
break;
case VARIABLE:
gen(LOD,lev-table[i].other.inOther.level,table[i].other.inOther.adr);
break;
case PROCEDURE:
error(21);
break;
}
getsym();
}
else if (sym ==NUMBER)
{
if (num>amax)
{
error(31);
num= 0;
}
gen(LIT,0,num);
getsym();
}
else if( sym ==LPAREN)
{
getsym();
symset tmp=fsys;
tmp.insert(RPAREN);
expression(tmp,tx,lev);
if (sym == RPAREN)
getsym();
else
error(22);
}
test(fsys,facbegsys,23);
}
}//factor end
void PL0::term(symset fsys,int tx,int lev)
{
if(sourceEnd)
return;
symbol mulop;
symset tmp=fsys;
for(int t=TIMES;t<=SLASH;t++)
tmp.insert((symbol)t);
factor(tmp,tx,lev);
while( sym>=TIMES && sym<=SLASH)
{
mulop= sym;
getsym();
factor(tmp,tx,lev);
if (mulop ==TIMES)
gen(OPR,0,4);
else
gen(OPR,0,5);
}
}// term end
void PL0::expression(symset fsys,int tx,int lev)
{
symbol addop;
symset tmp=fsys;
for(int t=PLUS;t<=MINUS;t++)
tmp.insert((symbol)t);
if( sym>=PLUS&&sym<=MINUS)
{
addop= sym;
getsym();
term(tmp,tx,lev);
if( addop ==MINUS)
gen(OPR,0,1);
}
else
term(tmp,tx,lev);
while (sym >=PLUS&&sym<=MINUS)
{
addop= sym;
getsym();
term(tmp,tx,lev);
if (addop ==PLUS)
gen(OPR,0,2);
else
gen(OPR,0,3);
}
}// expression end
void PL0::condition(symset fsys,int tx,int lev)
{
symbol relop;
symset tmp=fsys;
tmp.insert(EQL),tmp.insert(NEQ),tmp.insert(LSS),tmp.insert(LEQ),tmp.insert(GTR),tmp.insert(GEQ);
if( sym ==ODDSYM)
{
getsym();
expression(fsys,tx,lev);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -