📄 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++;//行数加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);
}
//读到的第一个字符是数字,则进入常数处理
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","常数太大~");
}
//把解析到的数字写入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="算术因子里出现非整型变量";
break;
case 3:
errorInfo="丢失')'";
break;
case 4:
errorInfo="算术表示不能以此符号开始";
break;
case 5:
errorInfo="逻辑表达式里出现函数名";
break;
case 6:
errorInfo="逻辑表达式不能以此符号开始";
break;
case 7:
errorInfo="非法的变量名";
break;
case 8:
errorInfo="丢失')'";
break;
case 9:
errorInfo="非法的参数名";
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="语句后出现非法字符";
break;
case 18:
errorInfo="变量定义后出现非法字符";
break;
case 19:
errorInfo="丢失','";
break;
case 20:
errorInfo="变量定义不能以此符号开始";
break;
case 21:
errorInfo="变量定义后出现非法字符";
break;
case 22:
errorInfo="此处应为\":=\"";
break;
case 23:
errorInfo="此处不能为函数名";
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="此处应为函数名";
break;
case 30:
errorInfo="语句不能以此符号开始";
break;
case 31:
errorInfo="语句后不能跟此符号";
break;
case 32:
errorInfo="算术表达式不能以此符号开始";
break;
case 33:
errorInfo="丢失'('";
break;
case 34:
errorInfo="逻辑表达式后出现非法字符";
break;
case 35:
errorInfo="函数定义后出现非法字符";
break;
case 36:
errorInfo="多余的';'";
break;
case 37:
errorInfo="这里等待一个'*'或'/'";
break;
case 38:
errorInfo="这里等待一个'+'或'-'";
break;
case 39:
errorInfo="参数个数不符";
break;
case 40:
errorInfo="函数定义需以procedure开始";
break;
case 41:
errorInfo="函数定义后出现非法字符";
break;
case 42:
errorInfo="外层不能访问内层的变量或调用内层函数";
break;
case 43:
errorInfo="除数为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 + -