?? plxcompiler.cpp
字號:
/************************************************
* *
* Purpose :the body of the PLX Compiler *
* Created by :tinysun *
* *
************************************************/
#include "PLXCompiler.h"
/***********************************************
* ------------ Key words of PLX --------------*
***********************************************/
string word[]=
{
" ",
"and ",
"begin ",
"call ",
"do ",
"else ",
"end ",
"false ",
"for ",
"from ",
"if ",
"integer ",
"logical ",
"not ",
"or ",
"procedure ",
"program ",
"read ",
"repeat ",
"then ",
"to ",
"true ",
"until ",
"while ",
"write "
};
int wsym[]=
{
0,
ANDSYM,BEGINSYM,CALLSYM,DOSYM,ELSESYM,ENDSYM,
FALSESYM,FORSYM,FROMSYM,IFSYM,INTESYM,LOGISYM,
NOTSYM,ORSYM,PROSYM,PROGSYM,READSYM,REPEATSYM,
THENSYM,TOSYM,TRUESYM,UNTILSYM,WHILESYM,WRITESYM
};
int ssym[127];
PLXCompiler::PLXCompiler()
{
}
PLXCompiler::PLXCompiler(char* pSource)
{
Init();
this->m_pfSource=fopen(pSource,"r");
if(m_pfSource==NULL)
{
exit(0);
}
}
PLXCompiler::~PLXCompiler()
{
if(this->m_pfSource)
{
fclose(this->m_pfSource);
}
}
void PLXCompiler::Init()
{
m_ch=' ';
memset(m_id,'\0',sizeof(m_id));
memset(m_line,'\0',sizeof(m_line));
memset(ssym,NUL,sizeof(ssym));
m_sym=NUL;
m_cc=0;
m_ln=0;
m_ll=0;
m_err=0;
m_cx=0;
m_tx=0;
m_isEnd=false;
ssym['+']=PLUS;
ssym['-']=MINUS;
ssym['*']=TIMES;
ssym['/']=SLASH;
ssym['(']=LPAREN;
ssym[')']=RPAREN;
ssym['=']=EQL;
ssym[',']=COMMA;
ssym[';']=SEMICOLON;
ssym['.']=PERIOD;
ssym['<']=LSS;
ssym['>']=GTR;
m_firsts.insert(IDENT);
m_firsts.insert(IFSYM);
m_firsts.insert(WHILESYM);
m_firsts.insert(REPEATSYM);
m_firsts.insert(WRITESYM);
m_firsts.insert(READSYM);
m_firsts.insert(FORSYM);
m_firsts.insert(CALLSYM);
m_follows.insert(SEMICOLON);
m_follows.insert(ENDSYM);
m_follows.insert(ELSESYM);
m_follows.insert(UNTILSYM);
m_followss.insert(ENDSYM);
m_followss.insert(ELSESYM);
m_followss.insert(UNTILSYM);
m_followae.clear();
m_followae=m_follows;
m_followae.insert(RPAREN);
m_followae.insert(DOSYM);
m_followae.insert(THENSYM);
m_followae.insert(ANDSYM);
m_followae.insert(ORSYM);
m_followbe.insert(RPAREN);
m_followbe.insert(THENSYM);
m_followbe.insert(DOSYM);
m_firstaf.insert(IDENT);
m_firstaf.insert(NUMBER);
m_firstaf.insert(LPAREN);
m_firstbf.insert(IDENT);
m_firstbf.insert(TRUESYM);
m_firstbf.insert(FALSESYM);
m_firstbf.insert(NOTSYM);
m_firstbf.insert(LPAREN);
m_firstbf.insert(NUMBER);
}
//判斷一個字符是否為制表字符
bool PLXCompiler::isTable(char ch)
{
return (' '==ch || '\t'==ch);
}
//
void PLXCompiler::removeNote(char *pstr,int len)
{
int i=0;
for(;i<len;i++)
{
if(pstr[i]=='/')
{
if((i+1)<len && pstr[i+1]=='/') //開始過濾注釋
{
pstr[i]=' ';
pstr[i+1]='\0';
break;
}
}
}
}
//只支持單行注釋 (//.....)
void PLXCompiler::getCh()
{
if(this->m_cc==this->m_ll)
{
memset(m_line,'\0',lineLength);
if(feof(this->m_pfSource)) //文件結束
{
if(this->m_sym!=PERIOD)
{
//fprintf(this->m_pfError,"%s\n","--Program incomplete--");
error(0);
}
m_isEnd=true;
return;
}
m_cc=0;
fgets(this->m_line,lineLength-1,this->m_pfSource); //讀取一行
//去除注釋
removeNote(this->m_line,strlen(m_line));
m_ll=strlen(this->m_line);
this->m_ln++;//行數(shù)加1
if(m_line[m_ll-1]==10)//過濾掉 '\r'
{
//ll--;
m_line[m_ll-1]=' ';
}
}
m_ch= m_line[m_cc];
m_cc= m_cc+1;
}
//獲取一個token
void PLXCompiler::getSym()
{
int k=0;
int i=0,j;
memset(m_id,'\0',sizeof(m_id));
if(m_isEnd) //源文件已讀到結束
return;
//獲取一個token的第一個字母
while(isTable(m_ch) && !m_isEnd)
getCh();
//讀到的第一個字符是26個英文字符,則進入標識符或關鍵字處理
if(isalpha(m_ch))
{
while(k<al-1 && (isalpha(m_ch) || isdigit(m_ch)))
{
m_id[k++]=m_ch;
if(m_isEnd)
break;
getCh();
}
for(i=k;i<al-1;i++)
{
m_id[i]=' ';
}
//利用二分查找來查詢關鍵字
i=1;
j=norw;
while(j>=i)
{
k=(i+j)/2;
if(strcmp(m_id,word[k].c_str())>0)
i=k+1;
else if(strcmp(m_id,word[k].c_str())<0)
j=k-1;
else
break;
}
//未找到,說明id 不是關鍵字, 而是標識符
if(i-1>=j)
{
m_sym=IDENT;
}
else
{
m_sym=(symbol)wsym[k];
}
//把解析到的一個token寫入result文件
//fprintf(this->m_pfResult,"(%d,%d)%s\n",this->m_ln,this->m_cc-1,m_id);
}
//讀到的第一個字符是數(shù)字,則進入常數(shù)處理
else if(isdigit(m_ch))
{
k=0;
m_num=0;
m_sym=NUMBER;
while(k<=nmax && isdigit(m_ch))
{
m_num=m_num*10+(m_ch-'0');
k++;
if(m_isEnd)
break;
getCh();
}
if(k>nmax)
{
error(0);
//fprintf(this->m_pfError,"%s","常數(shù)太大~");
}
//把解析到的數(shù)字寫入result文件
//fprintf(this->m_pfResult,"(%d,%d)%d\n",this->m_ln,this->m_cc-k,m_num);
}
//以下處理雙字符組成的token,如::=、>=、<=、/=
else if(':'==m_ch)
{
if(m_isEnd)
{
m_sym=NUL; //非法token
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-1,m_ch);
}
else
{
getCh();
if('='==m_ch)//處理賦值符號":="
{
m_sym=BECOMES;
getCh();
//fprintf(this->m_pfResult,"(%d,%d)%s\n",this->m_ln,this->m_cc-2,":=");
}
else
{
m_sym=NUL;//非法token
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-2,":");
}
}
}
else if('>'==m_ch)
{
if(m_isEnd)
{
m_sym=GTR;
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-1,m_ch);
}
else
{
getCh();
if('='==m_ch)//">="
{
m_sym=GEQ;
getCh();
//fprintf(this->m_pfResult,"(%d,%d)%s\n",this->m_ln,this->m_cc-2,">=");
}
else
{
m_sym=GTR;
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-2,'>');
}
}
}
else if('<'==m_ch)
{
if(m_isEnd)
{
m_sym=LSS;
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-1,m_ch);
}
else
{
getCh();
if('='==m_ch)//"<="
{
m_sym=LEQ;
getCh();
//fprintf(this->m_pfResult,"(%d,%d)%s\n",this->m_ln,this->m_cc-2,"<=");
}
else
{
m_sym=LSS;
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-2,'<');
}
}
}
else if('/'==m_ch)
{
if(m_isEnd)
{
m_sym=SLASH;
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-1,m_ch);
}
else
{
getCh();
if('='==m_ch)//"/="
{
m_sym=NEQ;
getCh();
//fprintf(this->m_pfResult,"(%d,%d)%s\n",this->m_ln,this->m_cc-2,"/=");
}
else
{
m_sym=SLASH;
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-2,'/');
}
}
}
else //處理單個字符
{
m_sym=(symbol)ssym[m_ch];
//fprintf(this->m_pfResult,"(%d,%d)%c\n",this->m_ln,this->m_cc-1,m_ch);
getCh();
}
}
//出錯處理~
void PLXCompiler::error(int errorNum)
{
this->m_err++;
string errorInfo;
if(this->m_err>maxerr)
{
printf("%s\n","----Too many errors------");
exit(0);
}
switch (errorNum)
{
case 0:
errorInfo="程序需以'.'結束";
break;
case 1:
errorInfo="用了未定義的變量";
break;
case 2:
errorInfo="算術因子里出現(xiàn)非整型變量";
break;
case 3:
errorInfo="丟失')'";
break;
case 4:
errorInfo="算術表示不能以此符號開始";
break;
case 5:
errorInfo="邏輯表達式里出現(xiàn)函數(shù)名";
break;
case 6:
errorInfo="邏輯表達式不能以此符號開始";
break;
case 7:
errorInfo="非法的變量名";
break;
case 8:
errorInfo="丟失')'";
break;
case 9:
errorInfo="非法的參數(shù)名";
break;
case 10:
errorInfo="丟失begin關鍵字";
break;
case 11:
errorInfo="丟失end關鍵字";
break;
case 12:
errorInfo="開始符號不是program";
break;
case 13:
errorInfo="此處應為整型變量";
break;
case 14:
errorInfo="關系表達式不能以此符號開始";
break;
case 15:
errorInfo="此處應為一個比較符號";
break;
case 16:
errorInfo="丟失';'";
break;
case 17:
errorInfo="語句后出現(xiàn)非法字符";
break;
case 18:
errorInfo="變量定義后出現(xiàn)非法字符";
break;
case 19:
errorInfo="丟失','";
break;
case 20:
errorInfo="變量定義不能以此符號開始";
break;
case 21:
errorInfo="變量定義后出現(xiàn)非法字符";
break;
case 22:
errorInfo="此處應為\":=\"";
break;
case 23:
errorInfo="此處不能為函數(shù)名";
break;
case 24:
errorInfo="缺了then";
break;
case 25:
errorInfo="缺了from";
break;
case 26:
errorInfo="缺了do";
break;
case 27:
errorInfo="缺了until";
break;
case 28:
errorInfo="缺了to";
break;
case 29:
errorInfo="此處應為函數(shù)名";
break;
case 30:
errorInfo="語句不能以此符號開始";
break;
case 31:
errorInfo="語句后不能跟此符號";
break;
case 32:
errorInfo="算術表達式不能以此符號開始";
break;
case 33:
errorInfo="丟失'('";
break;
case 34:
errorInfo="邏輯表達式后出現(xiàn)非法字符";
break;
case 35:
errorInfo="函數(shù)定義后出現(xiàn)非法字符";
break;
case 36:
errorInfo="多余的';'";
break;
case 37:
errorInfo="這里等待一個'*'或'/'";
break;
case 38:
errorInfo="這里等待一個'+'或'-'";
break;
case 39:
errorInfo="參數(shù)個數(shù)不符";
break;
case 40:
errorInfo="函數(shù)定義需以procedure開始";
break;
case 41:
errorInfo="函數(shù)定義后出現(xiàn)非法字符";
break;
case 42:
errorInfo="外層不能訪問內層的變量或調用內層函數(shù)";
break;
case 43:
errorInfo="除數(shù)為0";
break;
}
printf("%d:%s--%s(line:%d,column:%d)\n",errorNum,this->m_id,errorInfo.c_str(),this->m_ln,this->m_cc-1);
//exit(0);
}
//
void PLXCompiler::test(symset s1,symset s2,int errorNum)
{
symset s;
s.clear();
if(s1.find(m_sym)==s1.end()) //m_sym不在s1中
{
error(errorNum);
set_union(s1.begin(),s1.end(),s2.begin(),s2.end(),insert_iterator<symset>(s,s.begin()));
while(!this->m_isEnd && s.find(m_sym)==s.end())
getSym();
}
}
//enter a function item into table
void PLXCompiler::enter(objectt k,int lev)
{
item _item;
memset(&_item,'\0',sizeof(_item));
_item.kind=k;
if(_item.kind==pident)
{
_item.num=0;
}
_item.level=lev;
strcpy(_item.name,m_id);
m_tx++;
m_table.push_back(_item);
}
//
void PLXCompiler::enter(objectt k,int &dx,int lev)
{
item _item;
memset(&_item,'\0',sizeof(_item));
_item.kind=k;
if(_item.kind==bident ||_item.kind==aident)//變量
{
_item.adr=dx;
dx++;
}
_item.level=lev;
strcpy(_item.name,m_id);
m_tx++;
m_table.push_back(_item);
}
//
vector<item>::iterator PLXCompiler::position(alfa name)
{
int i=0;
vector<item>::iterator iter=m_table.end()-1;
for(; i<m_table.size(); iter--,i++)
{
if(strcmp(name,iter->name)==0)
break;
}
return (i==m_table.size() ? NULL :iter);
}
// 處理re非終結符
void PLXCompiler::RelationExpression(int level,symset fsys)
{
symset tmp;
symbol op;
tmp.insert(IDENT);
tmp.insert(NUMBER);
test(tmp,fsys,14);
if(m_sym==IDENT || m_sym==NUMBER)
{
if(m_sym==IDENT) //檢查變量需為整型
{
//查找符號表
vector<item>::iterator iter=this->position(m_id);
if(NULL==iter)
{
error(1); //變量為定義
}
else
{
if(iter->kind!=aident)
{
error(13);//此處變量需為整型
}
else
{
gen(LOD,level-iter->level,iter->adr);
}
}
getSym();
}
else
{
gen(LIT,0,this->m_num);
getSym();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -