编译原理pl0课本代码Word文档格式.docx

上传人:b****6 文档编号:17184797 上传时间:2022-11-28 格式:DOCX 页数:45 大小:26.46KB
下载 相关 举报
编译原理pl0课本代码Word文档格式.docx_第1页
第1页 / 共45页
编译原理pl0课本代码Word文档格式.docx_第2页
第2页 / 共45页
编译原理pl0课本代码Word文档格式.docx_第3页
第3页 / 共45页
编译原理pl0课本代码Word文档格式.docx_第4页
第4页 / 共45页
编译原理pl0课本代码Word文档格式.docx_第5页
第5页 / 共45页
点击查看更多>>
下载资源
资源描述

编译原理pl0课本代码Word文档格式.docx

《编译原理pl0课本代码Word文档格式.docx》由会员分享,可在线阅读,更多相关《编译原理pl0课本代码Word文档格式.docx(45页珍藏版)》请在冰豆网上搜索。

编译原理pl0课本代码Word文档格式.docx

//输出源文件及其各行对应的首地址

FILE*fa2;

//输出结果

boollistswitch;

//显示虚拟机代码与否

booltableswitch;

//显示名字表与否

charch;

//获取字符的缓冲区,getch使用

enumsymbolsym;

//当前的符号

charid[al+1];

//当前ident,多出的一个字节用于存放0

intnum;

//当前number

intcc,ll;

//getch使用的计数器,cc表示当前字符(ch)的位置

intcx;

//虚拟机代码指针,取值范围[0,cxmax-1]

charline[81];

//读取行缓冲区

chara[al+1];

//临时符号,多出的一个字节用于存放0

structinstructioncode[cxmax];

//存放虚拟机代码的数组

charword[norw][al];

//保留字

enumsymbolwsym[norw];

//保留字对应的符号值

enumsymbolssym[256];

//单字符的符号值

charmnemonic[fctnum][5];

//虚拟机代码指令名称

booldeclbegsys[symnum];

//表示声明开始的符号集合

boolstatbegsys[symnum];

//表示语句开始的符号集合

boolfacbegsys[symnum];

//表示因子开始的符号集合

////////////////////////////

////////Page455

//名字表结构

structtablestruct

charname[al];

//名字

enumobjectkind;

//类型:

const,var,arrayorprocedure

intval;

//数值,仅const使用

intlevel;

//所处层,仅const不使用

intadr;

//地址,仅const不使用

intsize;

//需要分配的数据区空间,仅procedure使用

structtablestructtable[txmax];

//名字表

FILE*fin;

FILE*fout;

charfname[al];

interr;

//当函数中会发生fatalerror时,返回-1告知调用它的函数,最终退出程序

#definegetsymdoif(-1==getsym())return-1

#definegetchdoif(-1==getch())return-1

#definetestdo(a,b,c)if(-1==test(a,b,c))return-1

#definegendo(a,b,c)if(-1==gen(a,b,c))return-1

#defineexpressiondo(a,b,c)if(-1==expression(a,b,c))return-1

#definefactordo(a,b,c)if(-1==factor(a,b,c))return-1

#definetermdo(a,b,c)if(-1==term(a,b,c))return-1

#defineconditiondo(a,b,c)if(-1==condition(a,b,c))return-1

#definestatementdo(a,b,c)if(-1==statement(a,b,c))return-1

#defineconstdeclarationdo(a,b,c)if(-1==constdeclaration(a,b,c))return-1

#definevardeclarationdo(a,b,c)if(-1==vardeclaration(a,b,c))return-1

voiderror(intn);

intgetsym();

intgetch();

voidinit();

intgen(enumfctx,inty,intz);

inttest(bool*s1,bool*s2,intn);

intinset(inte,bool*s);

intaddset(bool*sr,bool*s1,bool*s2,intn);

intsubset(bool*sr,bool*s1,bool*s2,intn);

intmulset(bool*sr,bool*s1,bool*s2,intn);

intblock(intlev,inttx,bool*fsys);

voidinterpret();

intfactor(bool*fsys,int*ptx,intlev);

intterm(bool*fsys,int*ptx,intlev);

intcondition(bool*fsys,int*ptx,intlev);

intexpression(bool*fsys,int*ptx,intlev);

intstatement(bool*fsys,int*ptx,intlev);

voidlistcode(intcx0);

intvardeclaration(int*ptx,intlev,int*pdx);

intconstdeclaration(int*ptx,intlev,int*pdx);

intposition(char*idt,inttx);

voidenter(enumobjectk,int*ptx,intlev,int*pdx);

intbase(intl,int*s,intb);

#include"

string.h"

#definestacksize500

intmain()

boolnxtlev[symnum];

printf("

Inputpl/0file?

"

);

scanf("

%s"

fname);

//输入文件名以后恢复

//strcpy(fname,"

begin"

fin=fopen(fname,"

r"

if(fin)

{

printf("

Listobjectcode?

(Y/N)"

//是否输入虚拟机代码

scanf("

listswitch=(fname[0]=='

y'

||fname[0]=='

Y'

Listsymboltable?

//是否输出名字表

tableswitch=(fname[0]=='

fa1=fopen("

fa1.tmp"

"

w"

fprintf(fa1,"

%s\n"

init();

//初始化

err=0;

cc=cx=ll=0;

ch='

'

;

if(-1!

=getsym())

{

fa=fopen("

fa.tmp"

fas=fopen("

fas.tmp"

//////////////////////////////////////////////

//////Page430

addset(nxtlev,declbegsys,statbegsys,symnum);

nxtlev[period]=true;

if(-1==block(0,0,nxtlev))//调用编译程序

{

fclose(fa);

fclose(fa1);

fclose(fas);

fclose(fin);

printf("

\n"

return0;

}

fclose(fa);

fclose(fa1);

fclose(fas);

if(sym!

=period)

error(9);

if(err==0)

fa2=fopen("

fa2.tmp"

interpret();

//调用解释执行程序

fclose(fa2);

else

Errorsinpl/0program"

}

fclose(fin);

}

else

Can'

topenfile!

return0;

}

voidinit()

inti;

//设置单字符符号

for(i=0;

i<

=255;

i++)

ssym[i]=nul;

ssym['

+'

]=plus;

-'

]=minus;

*'

]=times;

/'

]=slash;

('

]=lparen;

)'

]=rparen;

='

]=eql;

'

]=comma;

.'

]=period;

#'

]=neq;

'

]=semicolon;

//设置保留字名字,按照字母顺序,便于折半查找

strcpy(&

(word[0][0]),"

(word[1][0]),"

call"

(word[2][0]),"

const"

(word[3][0]),"

do"

(word[4][0]),"

end"

(word[5][0]),"

if"

(word[6][0]),"

odd"

(word[7][0]),"

procedure"

(word[8][0]),"

read"

(word[9][0]),"

then"

(word[10][0]),"

var"

(word[11][0]),"

while"

(word[12][0]),"

write"

//设置保留字符号

wsym[0]=beginsym;

wsym[1]=callsym;

wsym[2]=constsym;

wsym[3]=dosym;

wsym[4]=endsym;

wsym[5]=ifsym;

wsym[6]=oddsym;

wsym[7]=procsym;

wsym[8]=readsym;

wsym[9]=thensym;

wsym[10]=varsym;

wsym[11]=whilesym;

wsym[12]=writesym;

//设置指令名称

(mnemonic[lit][0]),"

lit"

(mnemonic[opr][0]),"

opr"

(mnemonic[lod][0]),"

lod"

(mnemonic[sto][0]),"

sto"

(mnemonic[cal][0]),"

cal"

(mnemonic[inte][0]),"

inte"

(mnemonic[jmp][0]),"

jmp"

(mnemonic[jpc][0]),"

jpc"

//设置符号集

symnum;

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;

//设置因子开始符号集

facbegsys[ident]=true;

facbegsys[number]=true;

facbegsys[lparen]=true;

//用数组实现集合的集合运算

intinset(inte,bool*s)

returns[e];

intaddset(bool*sr,bool*s1,bool*s2,intn)

n;

sr[i]=s1[i]||s2[i];

intsubset(bool*sr,bool*s1,bool*s2,intn)

sr[i]=s1[i]&

&

(!

s2[i]);

intmulset(bool*sr,bool*s1,bool*s2,intn)

s2[i];

voiderror(intn)

charspace[81];

memset(space,32,81);

space[cc-1]=0;

//出错时当前符号已经读完,所以cc-1

****%s!

%d\n"

space,n);

fprintf(fa1,"

err++;

intgetch()

if(cc==ll)

if(feof(fin))

printf("

programincomplete"

return-1;

ll=0;

cc=0;

%d"

cx);

while(ch!

=10)

//fscanf(fin,"

%c"

&

ch)

if(EOF==fscanf(fin,"

ch))

line[ll]=0;

break;

ch);

fprintf(fa1,"

line[ll]=ch;

ll++;

ch=line[cc];

cc++;

//////////////////////////////////////////

//////////词法分析,获取一个符号

intgetsym()

inti,j,k;

while(ch=='

||ch==10||ch==9)//忽略空格,换行和tab

getchdo;

if(ch>

a'

ch<

z'

k=0;

do

if(k<

al)

a[k]=ch;

k++;

getchdo;

}while(ch>

||ch>

0'

9'

a[k]=0;

strcpy(id,a);

i=0;

j=norw-1;

{//搜索当前符号是否为保留字

k=(i+j)/2;

if(strcmp(id,word[k])<

=0)

j=k-1;

if(strcmp(id,word[k])>

i=k+1;

}while(i<

=j);

if(i-1>

j)

sym=wsym[k];

else

sym=ident;

//搜索失败,则是名字或数字

if(ch>

{//检测是否为数字:

以0...9开头

k=0;

num=0;

sym=number;

do

num=10*num+ch-'

getchdo;

}while(ch>

//获取数字的值

k--;

if(k>

nmax)

error(30);

if(ch=='

:

)//检测赋值符号

if(ch=='

{

sym=becomes;

getchdo;

}

else

sym=nul;

//不能识别的符号

<

)//检测i小于或小于等于符号

if(ch=='

{

sym=leq;

getchdo;

}

else

sym=lss;

>

)//检测大于或大于等于符号

if(ch=='

{

sym=geq;

getchdo;

}

else

sym=gtr;

sym=ssym[ch];

//当符号不满足上述条件时,全部按照单字符符号处理

//getchdo

//rechjard

if(sym!

//endrichard

intgen(enumfctx,inty,intz)

if(cx>

=cxmax)

Programtoolong"

//程序过长

return-1;

code[cx].f=x;

code[cx].l=y;

code[cx].a=z;

cx++;

////////////////////////////////////////////////

//测试当前符号是否合法

//在某一部分(如一条语句,一个表达式)将要结束时,我们希望下一个符号属于某集合

//(该部分的后跟符号),test负责这项检测,并且负责当检测不通过时的补救措施

//程序在需要检测时指定当前需要的符号集合和补救用的集合(如之前未完成部分的后跟符号),以及检测不通过时的错误符号

//s1:

我们需要的符号

//s2:

如果不是我们需要的,则需要一个补救用的集合

//n:

错误号

inttest(bool*s1,bool*s2,intn)

if(!

inset(sym,s1))

error(n);

//当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合

while((!

inset(sym,s1))&

inset(sym,s2)))

getsymdo;

///////////////////////////////

//编译程序主体

//lev:

当前分程序所在层

//tx:

名字表当前尾指针

//fsys:

当前模块后跟符号

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1