文档库 最新最全的文档下载
当前位置:文档库 › 编译原理PL0报告(附源码教程)

编译原理PL0报告(附源码教程)

编译原理PL0报告(附源码教程)
编译原理PL0报告(附源码教程)

编译原理课程设计

学院计算机学院

专业计算机科学与技术班级

学号

姓名

指导教师

20 年月日

一、课程设计要求

基本内容(成绩范围:“中”、“及格”或“不及格”)

(1)扩充赋值运算:*= 和/=

扩充语句(Pascal的FOR语句):

①FOR <变量>:=<表达式> TO <表达式> DO <语句>

②FOR <变量>:=<表达式> DOWNTO <表达式> DO <语句>

其中,语句①的循环变量的步长为2,

语句②的循环变量的步长为-2。

(3)增加运算:++ 和--。

选做内容(成绩评定范围扩大到:“优”和“良”)

(1)增加类型:①字符类型;②实数类型。(2)扩充函数:①有返回值和返回语句;②有参数函数。(3)增加一维数组类型(可增加指令)。

(4)其他典型语言设施。

二、概述

目标:实现PL0某些特定语句

实现语言:C语言

实现工具平台:VS201

运行平台:WIN7

三、结构设计说明与功能块描述

PL/0编译程序的结构图

PL/0编译程序的总体流程图

四、主要成分描述

1、符号表

编译程序里用了一个枚举类型enum symbol,然后定义了enum symbol sym来存放当前

的符号,前面讲过,主程序定义了一个以字符为元素的一维数组word,称保留字表,这个保留字表也存放在符号表里,为了识别当前的符号是属于哪些保留字;还有标识符,拼数,拼符合词等的符号名都存放在符号表里,当sym存放当前的符号时,我们可以判断它是属于哪类的符号,然后加以处理。

在运行的过程中,主程序中又定义了一个名字表,也就是符号表,来专门存放变量、常量和过程名的各个属性,里面的属性包括name,kind,val/level,adr,size,我们来举一个PL/0语言过程说明部分的片段:

Const a=35,b=49;

Var c,d,e;

Procedure p;

Var g;

当遇到标识符的引用时就调用position函数,根据当前sym的符号类型来查table表,看是否有过正确的定义,若已有,则从表中取相应的有关信息,供代码的生成用。若无定义则调用出错处理程序。

2、运行时存储组织和管理

对于源程序的每一个过程(包括主程序),在被调用时,首先在数据段中开辟三个空间,存放静态链SL、动态链DL和返回地址RA。静态链记录了定义该过程的直接外过程(或主程序)运行时最新数据段的基地址。动态链记录调用该过程前正在运行的过程的数据段基址。返回地址记录了调用该过程时程序运行的断点位置。对于主程序来说,SL、DL和RA的值均置为0。静态链的功能是在一个子过程要引用它的直接或间接父过程(这里的父过程是按定义过程时的嵌套情况来定的,而不是按执行时的调用顺序定的)的变量时,可以通过静态链,跳过个数为层差的数据段,找到包含要引用的变量所在的数据段基址,然后通过偏移地址访问它。

在过程返回时,解释程序通过返回地址恢复指令指针的值到调用前的地址,通过当前段基址恢复数据段分配指针,通过动态链恢复局部段基址指针。实现子过程的返回。对于主程序来说,解释程序会遇到返回地址为0的情况,这时就认为程序运行结束。

解释程序过程中的base函数的功能,就是用于沿着静态链,向前查找相差指定层数的局部数据段基址。这在使用sto、lod、stoArr、lodArr等访问局部变量的指令中会经常用。

类PCODE代码解释执行的部分通过循环和简单的case判断不同的指令,做出相应的动作。当遇到主程序中的返回指令时,指令指针会指到0位置,把这样一个条件作为终至循环的条件,保证程序运行可以正常的结束。

3、语法分析方法

语法分析的任务是识别由词法分析给出的单词符号序列在结构上是否符合给定的文法规则.PL/0编译程序的语法分析采用了自顶向下的递归子程序法.粗略地说:就是对应每个非终结符语法单元,编一个独立的处理过程(或子程序).语法分析研究从读入第一个单词开始由非终结符程序即开始符出发,沿语法描述图箭头所指出的方向进行分析.当遇到非终结符时,则调用相应的处理过程,从语法描述图看也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行相应的语义程序(就是翻译程序).再读取下一个单词继续分析.遇到分支点时将当前的单词与分支点上的多个终结符逐个相比较,若都不匹配时可能是进入下一非终结符语法单位或是出错.

如果一个PL/0语言程序的单词序列在整修语法分析中,都能逐个得到匹配,直到程序结束’.’,这时就说所输入的程序是正确的.对于正确的语法分析做相应的语义翻译,最终得出目标程序.

4、中间代码表示

中间代码表示格式如下:

其中f代表功能码,l表示层次差,也就是变量或过程被引用的分程序与说明该变量或过程的分程序之间的层次差.a的含意对不同的指令有所区别,见下面对每条指令解释说明.

1.LIT 0 A将常数值取到栈顶,A为常数值

2.LOD L A将变量值取到栈顶,A为偏移量,L为层差

3.STO L A将栈顶内容送入某一变量单元中,A为偏移量,L为层差

4.CAL L A调用过程,A为过程地址,L为层差

5.INT 0 A在运行栈中为被调用的过程开辟A个单元的数据区

6.JMP 0 A无条件跳转到A地址

7.JPC 0 A条件跳转,当栈顶布尔值非真则跳转到A地址,否则顺序执行

8.OPR 0 0 过程调用结束后,返回调用点并退栈

9.OPR 0 1 栈顶元素取反

10.OPR 0 2 次栈顶与栈顶相加,退两个栈元素,结果值进栈

11.OPR 0 3 次栈顶减去栈顶,退两个栈元素,结果值进栈

12.OPR 0 4 次栈顶乘以栈顶,退两个栈元素,结果值进栈

13.OPR 0 5 次栈顶除以栈顶,退两个栈元素,结果值进栈

14.OPR 0 6 栈顶元素的奇偶判断,结果值在栈顶

15.OPR 0 7

16.OPR 0 8 次栈顶与栈顶是否相等,退两上栈元素,结果值进栈

17.OPR 0 9 次栈顶与栈顶是否不等,退两个栈元素,结果值进栈

18.OPR 0 10 次栈顶是否小于栈顶,退两个栈元素,结果值进栈

19.OPR 0 11 次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈

20.OPR 0 12 次栈顶是否大于栈顶,退两个栈元素,结果值进栈

21.OPR 0 13 次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈

22.OPR 0 14 栈顶值输出到屏幕

23.OPR 0 15 屏幕输出换行

24.OPR 0 16 从命令行读入一个输入置于栈顶

(后续增加的指令后面介绍)

五、测试用例

1、基本内容

PL0代码:for.txt

var a,b;

begin

a:=3;

b:=8;

a*=b;

b/=2;

write(a);

write(b);

repeat

a:=a+b;

until a>50;

write(a);

write(b);

for(a:=0;a<5;a++)

b--;

write(a);

write(b);

for a:=1 to 6 do b+=2;

for b:=9 downto 4 do a+=2; write(a);

write(b);

end.

结果截图:

2、选做内容

1)字符实型PL0:charreal.txt char x;

char y;

real r;

real s;

begin

x:='a';

y:='b';

read(r);

read(s);

write(x);

write(y);

write(r);

write(s);

s:=s-r;

write(s);

read(x);

read(y);

write(x);

write(y);

s:=7.344;

r:=4.511;

s:=s-r;

write(s);

end.

结果截图:

2)数组PL0:shuzu.txt var a[4];

var r1,r2,r3,r4;

begin

a[0]:=55;

a[1]:=66;

a[2]:=77;

a[3]:=88;

r1:=11;

r2:=22;

r3:=33;

r4:=44;

a[3]:=a[0]+a[1];

a[2]:=a[1]-r1;

r1:=a[0]+a[1];

r2:=a[1]+r3;

write(a[0]);

write(a[1]);

write(a[2]);

write(a[3]);

write(r1);

write(r2);

write(r3);

write(r4);

read(a[0]);

read(a[1]);

read(a[2]);

read(a[3]);

write(a[0]);

write(a[1]);

write(a[2]);

write(a[3]);

r1:=0;

r2:=1;

r3:=2;

r4:=3;

a[r1]:=55;

a[r2]:=66;

a[r3]:=77;

a[r4]:=88;

write(a[r1]);

write(a[r2]);

write(a[r3]);

write(a[r4]);

read(a[r1]);

read(a[r2]);

read(a[r3]);

read(a[r4]);

write(a[r1]);

write(a[r2]);

write(a[r3]);

write(a[r4]); end.

结果截图:

六、开发过程

1、实现++,--,*=,/=比较简单,过程大致如下:

1)头文件中symbol枚举类型中得加上4个运算的保留字,修改symnum常量的大小以及保留字大小norw(都是+4)。

2)Init()函数里增加4个运算保留字单词(得按照字母顺序)。

3)Getsym()函数中增加对这4个运算符的分析,较简单就不列举了。

4)Statement()函数中增加对运算符的解释生成代码,如下所示:

switch(sym)

{

case becomes: //如果的确为赋值号

getsymdo; //获取下一个token,正常应为一个表达式

memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

break;

case incsym: //如果为++

gendo(lod,lev-table[i].level,table[i].adr);

gendo(lit,0,1);

gendo(opr,0,2);

getsymdo;

break;

case decsym: //如果为--

gendo(lod,lev-table[i].level,table[i].adr);

gendo(lit,0,1);

gendo(opr,0,3);

getsymdo;

break;

case muleqlsym: //如果为*=

gendo(lod,lev-table[i].level,table[i].adr);

getsymdo; //获取下一个token,正常应为一个表达式memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

gendo(opr,0,4);

break;

case diveqlsym: //如果是/=

gendo(lod,lev-table[i].level,table[i].adr);

getsymdo;

memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev);

gendo(opr,0,5);

break;

case inesym://+=

gendo(lod,lev-table[i].level,table[i].adr);

getsymdo; //获取下一个token,正常应为一个表达式memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

gendo(opr,0,2);

break;

case deesym://-=

gendo(lod,lev-table[i].level,table[i].adr);

getsymdo; //获取下一个token,正常应为一个表达式memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

gendo(opr,0,3);

break;

default:

error(8);

printf("程序体内语句部分的后跟符不正确\n");

break;

}

5)factor()因子函数也得添加++,--的分析,如下

while(sym==incsym||sym==decsym)

{

if(sym == incsym)

{

gendo(lit,0,1);

gendo(opr,0,2);

}

else

{

gendo(lit,0,1);

gendo(opr,0,3);

}

getsymdo;

}

2、实现for…to…..do…. 和for….downto….do….语句

1)增加保留字和增加运算符类似,不再说明。

2)主要修改的是statement()函数中for单词的解释生成代码,如下所示

if(sym==forsym) //如果遇到for语句

{

getsymdo;

if(sym==ident)

{

i=position(id,*ptx);

if(i==0) error(11);

else

{

if(table[i].kind!=variable) //赋值语句中,赋值号左部标识符属性应是变量

{

error(12);i=0;

}

else

{

getsymdo;

if(sym!=becomes) error(13); //赋值语句左部标识符后应是赋值号:=

else getsymdo;

memcpy(nxtlev,fsys,sizeof(bool)*symnum);

nxtlev[tosym]=true; //后跟符to和downto

nxtlev[downtosym]=true;

expressiondo(nxtlev,ptx,lev); //处理赋值语句右部的表达式E1

gendo(sto,lev-table[i].level,table[i].adr); //保存初值

switch(sym)

{

case tosym: //步长为的向上增加

getsymdo;

cx1=cx; //保存循环开始点

//将循环判断变量取出放到栈顶

gendo(lod,lev-table[i].level,table[i].adr);

memcpy(nxtlev,fsys,sizeof(bool)*symnum); //处理表达式E2

nxtlev[dosym]=true; //后跟符do

expressiondo(nxtlev,ptx,lev);/*判断循环变量条件,比如for i:=E1 to E2 do S中,判断i是否小于E2,如小于等于,继续循环,大于的话,跳出循环*/

gendo(opr,0,13); //生成比较指令,i是否小于等于E2的值

cx2=cx; //保存循环结束点

//生成条件跳转指令,跳出循环,跳出的地址未知

gendo(jpc,0,0);

if(sym==dosym) //处理循环体S

{

getsymdo;

statement(fsys,ptx,lev); //循环体处理

//增加循环变量步长为

//将循环变量取出放在栈顶

gendo(lod,lev-table[i].level,table[i].adr);

gendo(lit,0,2); //将步长取到栈顶

gendo(opr,0,2); //循环变量加步长

//将栈顶的值存入循环变量

gendo(sto,lev-table[i].level,table[i].adr);

gendo(jmp,0,cx1); //无条件跳转到循环开始点/*回填循环结束点的地址,cx为else后语句执行完的位置,它正是前面未定的跳转地址*/

code[cx2].a=cx;

}

else

{

error(29); //for语句中少了do

}

break;

case downtosym: //步长为的向下减少

getsymdo;

cx1=cx; //保存循环开始点

//将循环判断变量取出放到栈顶

gendo(lod,lev-table[i].level,table[i].adr);

memcpy(nxtlev,fsys,sizeof(bool)*symnum); //处理表达式E2

nxtlev[dosym]=true; //后跟符do

expressiondo(nxtlev,ptx,lev);

/*判断循环变量条件,比如for i:=E1 downto E2 do S中,判断i是否

大于等于E2,如大于等于,继续循环,小于的话,跳出循环*/

gendo(opr,0,11); //生成比较指令,i是否大于等于E2的值

cx2=cx; //保存循环结束点

//生成条件跳转指令,跳出循环,跳出的地址未知

gendo(jpc,0,0);

if(sym==dosym) //处理循环体S

{

getsymdo;

statement(fsys,ptx,lev); //循环体处理

//增加循环变量步长为

//将循环变量取出放在栈顶

gendo(lod,lev-table[i].level,table[i].adr);

gendo(lit,0,2); //将步长取到栈顶

gendo(opr,0,3); //循环变量加步长

//将栈顶的值存入循环变量

gendo(sto,lev-table[i].level,table[i].adr);

gendo(jmp,0,cx1); //无条件跳转到循环开始点

/*回填循环结束点的地址,cx为else后语句执行完的位置,它正是前面未定的跳转地址*/

code[cx2].a=cx;

}

else

{

error(29);//for语句中少了do

}

break;

}

}

}

}

3、增加一维数组

1)首先增加单字符’[’和’]’,symbol类型增加2个单词,枚举类型数量symnum加2,init()函数中单字符数组ssym增加2个单字符。

2)变量声明部分vardeclaration()函数需要增加数组声明,如下所示:

int vardeclaration(int *ptx,int lev,int *pdx)

{ // 变量声明处理

int num1,k,m;

if (sym==ident)

{

enter(variable,ptx,lev,pdx);

getsymdo;

}

else

error(4);

if(sym==lsquare) //标识符为'[',数组变量说明处理

{

getsymdo;

if(sym==number)

{

num1=(int)num; //长度为数字

*pdx=*pdx+num1-1; // 计算数组的长度并留出空间,移动指针

getsymdo;

}

else

{ //长度为标识符

m=position(id,*ptx); //查找标识符的位置

if(m==0)

error(11);

else if(table[m].kind==constant) //为常量

num1=table[m].val; //把其值赋给num1

else

{

error(41);

m=0;

}

*pdx=*pdx+num1-1;

getsymdo;

}

if(sym==rsquare) //标识符为数组的符号']',则取下一个单词

{

getsymdo;

}

else

{

error(61);

}

} //漏掉括号']'

return 0;

}

3)语句处理statement()函数中需要处理很多,首先确认标识符后需要辨认是否为数组,然后在read和write等语句分析部分需要辨认数组,分析主体大致如下

if(sym==ident) //以标识符开头,可能是赋值语句

{

i=position(id,*ptx); //在符号表中查到该标识符所在位置

if(i==0) //如果没找到

{

error(11); //抛出11号错误

printf("标识符未说明\n");

}

else

{

if(table[i].kind!=variable&&table[i].kind!=realcon&&table[i].kind!=charcon) //在符号表中找到该标识符,但该标识符不是变量名

{

error(12); //抛出12号错误

printf("赋值语句中,赋值号左部标识符属性应是变量\n");

i=0; // i置0作为错误标志

}

else

{

getsymdo; //获得下一个token,正常应为赋值号

//与书本不同的地方,在这里除了赋值号:=

//为/= *= ++ --

if(sym==lsquare)

{

getsymdo;

if(sym==number)

{

j1=(int)num;

getsymdo;

}

else if(sym==ident)

{

j2=position(id,*ptx);

j=1;

getsymdo;

}

else

error(60);

if(sym==rsquare) //判断下标后是否为']'

{

getsymdo;

tag=1;

}

else

error(61);

}

switch(sym)

{

case becomes: //如果的确为赋值号

getsymdo; //获取下一个token,正常应为一个表达式memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

break;

case incsym: //如果为++

if(j==1)

{

varnum[varn]=j2;

varn++;

gendo(lod2,lev-table[i].level,table[i].adr);

}

else

{

gendo(lod,lev-table[i].level,table[i].adr);

}

gendo(lit,0,1);

gendo(opr,0,2);

getsymdo;

break;

case decsym: //如果为--

if(j==1)

{

varnum[varn]=j2;

varn++;

gendo(lod2,lev-table[i].level,table[i].adr);

}

else

{

gendo(lod,lev-table[i].level,table[i].adr);

}

gendo(lit,0,1);

gendo(opr,0,3);

getsymdo;

break;

case muleqlsym: //如果为*=

if(j==1)

{

varnum[varn]=j2;

varn++;

gendo(lod2,lev-table[i].level,table[i].adr);

}

{

gendo(lod,lev-table[i].level,table[i].adr);

}

getsymdo; //获取下一个token,正常应为一个表达式memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

gendo(opr,0,4);

break;

case diveqlsym: //如果是/=

if(j==1)

{

varnum[varn]=j2;

varn++;

gendo(lod2,lev-table[i].level,table[i].adr);

}

else

{

gendo(lod,lev-table[i].level,table[i].adr);

}

getsymdo;

memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev);

gendo(opr,0,5);

break;

case inesym://+=

if(j==1)

{

varnum[varn]=j2;

varn++;

gendo(lod2,lev-table[i].level,table[i].adr);

}

else

{

gendo(lod,lev-table[i].level,table[i].adr);

}

getsymdo; //获取下一个token,正常应为一个表达式memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

gendo(opr,0,2);

case deesym://-=

gendo(lod,lev-table[i].level,table[i].adr);

getsymdo; //获取下一个token,正常应为一个表达式

memcpy(nxtlev,fsys,sizeof(bool)* symnum);

expressiondo(nxtlev,ptx,lev); //处理表达式

gendo(opr,0,3);

break;

default:

error(8);

printf("程序体内语句部分的后跟符不正确\n");

break;

}

if(i!=0)//如果不曾出错,i将不为0,i所指为当前语句

//左部标识符在符号表中的位置

{

if(j==1)

{

varnum[varn]=j2;

varn++;

gendo(sto2,lev-table[i].level,table[i].adr);

}

else

{

gendo(sto,lev-table[i].level,table[i].adr+j1); //产生一行把表达式值写往指定内存的sto目标代码

}

}

}

}

}

4)Factor()因子处理函数中也需要辨认数组,分析过程如下:

int factor(bool*fsys,int *ptx,int lev)

{

int i,j,tag=1,flag=0;

bool nxtlev[symnum];

testdo(facbegsys,fsys,24); //开始因子处理前,先检查当前token是否在facbegsys

//集合中。如果不是合法的token,抛24号错误,并通

//过fsys集恢复使语法处理可以继续进行

while(inset(sym,facbegsys)) //循环处理因子

{

if(sym==ident) //如果遇到的是标识符

{

i=position(id,*ptx); //查符号表,找到当前标识符在符号表中位置

if(i==0) //如果查符号表返回为0,表示没有找到标识符

{

error(11); //抛出11号错误

printf("标识符未说明\n");

}

else //如果在符号表中找到了当前标识符的位置,开始生成相应代码

{

switch(table[i].kind)

{

case constant: //如果这个标识符对应的是常量,值为val,生成lit指令,把val放到栈顶

gendo(lit,0,table[i].val);

break;

case variable: //如果标识符是变量名,生成lod指令把位于距

//离当前层level的层的偏移地址为adr的变量放到栈顶

getsymdo;

if(sym==lsquare) //'['

{

getsymdo;

if(sym==number)

{

fte=num;

getsymdo;

}

else if(sym==ident) //把数组的下标赋给j和fte

{

j=position(id,*ptx);

varnum[varn]=j;

varn++;

flag=1;

getsymdo;

}

else

{

error(60);

}

if(sym==rsquare)

{

编译原理课程设计

《编译原理》课程设计大纲 课程编号: 课程名称:编译原理/Compiler Principles 周数/学分:1周/1学分 先修课程:高级程序设计语言、汇编语言、离散数学、数据结构 适用专业:计算机科学与技术专业、软件工程专业 开课学院,系或教研室:计算机科学与技术学院 一、课程设计的目的 课程设计是对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。通常,设计题中的问题比平时的练习题要复杂,也更接近实际。编译原理这门课程安排的课程设计的目的是旨在要求学生进一步巩固课堂上所学的理论知识,深化理解和灵活掌握教学内容,选择合适的数据逻辑结构表示问题,然后编制算法和程序完成设计要求,从而进一步培养学生独立思考问题、分析问题、解决实际问题的动手能力。 要求学生在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法编制和程序代码的编写。 设计时间: 开发工具: (1) DOS环境下使用Turbo C; (2) Windows环境下使用Visual C++ 。 (3) 其它熟悉语言。 二、课程设计的内容和要求 设计题一:算术表达式的语法分析及语义分析程序设计。 1.目的

通过设计、编制、调试一个算术表达式的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词 法检查和分析。 2.设计内容及要求: 算术表达式的文法: 〈无符号整数〉∷= 〈数字〉{〈数字〉} 〈标志符〉∷= 〈字母〉{〈字母〉|〈数字〉} 〈表达式〉∷= [+|-]〈项〉{〈加法运算符〉〈项〉} 〈项〉∷= 〈因子〉{〈乘法运算符〉〈因子〉} 〈因子〉∷= 〈标志符〉|〈无符号整数〉|‘(’〈表达式〉‘)’ 〈加法运算符〉∷= +|- 〈乘法运算符〉∷= *|/ (1) 分别选择递归下降法、算符优先分析法(或简单优 先法)完成以上任务,中间代码选用逆波兰式。 (2) 分别选择LL(1)、LR法完成以上任务,中间代码选 用四元式。 (3) 写出算术表达式的符合分析方法要求的文法,给出 分析方法的思想,完成分析程序设计。 (4) 编制好分析程序后,设计若干用例,上机测试并通 过所设计的分析程序。 设计题二:简单计算器的设计 1.目的 通过设计、编制、调试一个简单计算器程序,加深对语法及语 义分析原理的理解,并实现词法分析程序对单词序列的词法检 查和分析。 2.设计内容及要求 算术表达式的文法:

编译原理课程设计报告_LL(1)分析过程模拟

课程设计(论文)任务书 软件学院学院软件工程专业07-1班 一、课程设计(论文)题目LL(1)分析过程模拟 二、课程设计(论文)工作自 2010 年 6 月 22日起至 2010 年 6月 28 日止。 三、课程设计(论文) 地点: 四、课程设计(论文)内容要求: 1.本课程设计的目的 (1)使学生掌握LL(1)模块的基本工作原理; (2)培养学生基本掌握LL(1)分析的基本思路和方法; (3)使学生掌握LL(1)的调试; (4)培养学生分析、解决问题的能力; (5)提高学生的科技论文写作能力。 2.课程设计的任务及要求 1)基本要求: (1)分析LL(1)模块的工作原理; (2)提出程序的设计方案; (3)对所设计程序进行调试。 2)创新要求: 在基本要求达到后,可进行创新设计,如改算法效率。 3)课程设计论文编写要求 (1)要按照书稿的规格打印誊写课程设计论文 (2)论文包括目录、绪论、正文、小结、参考文献、附录等 (3)课程设计论文装订按学校的统一要求完成 4)答辩与评分标准: (1)完成原理分析:20分; (2)完成设计过程(含翻译):40分; (3)完成调试:20分;

(4)回答问题:20分。 5)参考文献: (1)张素琴,吕映芝,蒋维杜,戴桂兰.编译原理(第2版).清华大学出版社 (2)丁振凡.《Java语言实用教程》北京邮电大学出版社 6)课程设计进度安排 内容天数地点 构思及收集资料2图书馆 编程与调试4实验室 撰写论文1图书馆、实验室 学生签名: 2009 年6 月22 日 课程设计(论文)评审意见 (1)完成原理分析(20分):优()、良()、中()、一般()、差();(2)设计分析(20分):优()、良()、中()、一般()、差();(3)完成调试(20分):优()、良()、中()、一般()、差();(4)翻译能力(20分):优()、良()、中()、一般()、差();(5)回答问题(20分):优()、良()、中()、一般()、差();(6)格式规范性及考勤是否降等级:是()、否() 评阅人:职称: 年月日

编译原理课程设计

编译原理课程设计报告 课题名称: C-语言编译器设计(scanner和parser) 提交文档学生姓名: 提交文档学生学号: 同组成员名单:无 指导教师姓名:金军 指导教师评阅成绩: 指导教师评阅意见: . . 提交报告时间: 2011年 6 月 17 日

1.课程设计目标 设计C-Minus编译器分为scanner和parser两个部分。scanner主要作用是对目标代码进行扫描,列出关键字,变量等内容;parser主要对语法进行分析并生成语法树。 2.分析与设计 ●实现方法:代码用C语言编译而成。其中scanner为手工实现,主要采用switch-case结构实现 状态转换;parser部分采用递归下降分析方法实现。 ●扫描器:C-的词法如下: 1、语言的关键字:i f el se i nt return void while 2、专用符号:+ - * /< <= > >= == != =; , ( ) [ ] { } /* */ 3、其他标记是变量(ID)和数字(NUM),通过下列正则表达式定义: ID = letter letter* NUM = di git digi t* letter = a|..|z|A|..|Z digi t = 0|..|9 4、空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开ID、NUM关键字 5. 注释用通常的C语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在 标记内)上,且可以超过一行。注释不能嵌套 其DFA图如下:

分析器:以下为C-的语法规则BNF:

编译原理实验报告

院系:计算机科学学院 专业、年级: 07计科2大班 课程名称:编译原理 学号姓名: 指导教师: 2010 年11月17 日 组员学号姓名

实验 名称 实验一:词法分析实验室9205 实验目的或要求 通过设计一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 具体要求:输入为某语言源代码,达到以下功能: 程序输入/输出示例:如源程序为C语言。输入如下一段: main() { int a,b; a=10; b=a+20; } 要求输出如下(并以文件形式输出或以界面的形式输出以下结果)。 (2,”main”) (5,”(“) (5,”)“) (5,”{“} (1,”int”) (2,”a”) (5,”,”) (2,”b”) (5,”;”) (2,”a”) (4,”=”) (3,”10”) (5,”;”) (2,”b”) (4,”=”) (2,”a”) (4,”+”) (3,”20”) (5,”;”) (5,”}“) 要求: 识别保留字:if、int、for、while、do、return、break、continue等等,单词种别码为1。 其他的标识符,单词种别码为2。常数为无符号数,单词种别码为3。 运算符包括:+、-、*、/、=、>、<等;可以考虑更复杂情况>=、<=、!= ;单词种别码为4。分隔符包括:“,”“;”“(”“)”“{”“}”等等,单词种别码为5。

编译原理词法分析和语法分析报告+代码(C语言版)

词法分析 一、实验目的 设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 2.1 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 : = + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 2.2 各种单词符号对应的种别码: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图: 主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,}; 图3-1 (2)程序中需要用到的主要变量为syn,token和sum 3.2 扫描子程序的算法思想: 首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

编译原理课程设计报告(一个完整的编译器)

编译原理程序设计报告 一个简单文法的编译器的设计与实现专业班级:计算机1406班 组长姓名:宋世波 组长学号: 20143753 指导教师:肖桐 2016年12月

设计分工 组长学号及姓名:宋世波20143753 分工:文法及数据结构设计 词法分析 语法分析(LL1) 基于DAG的中间代码优化 部分目标代码生成 组员1学号及姓名:黄润华20143740 分工:中间代码生成(LR0) 部分目标代码生成 组员2学号及姓名:孙何奇20143754 分工:符号表组织 部分目标代码生成

摘要 编译器是将便于人编写,阅读,维护的高级计算机语言翻译为计算机能解读、运行的低阶机器语言的程序。编译是从源代码(通常为高阶语言)到能直接被计算机或虚拟机执行的目标代码(通常为低阶语言或机器语言)的翻译过程。 一.编译器的概述 1.编译器的概念 编译器是将便于人编写,阅读,维护的高级计算机语言翻译为计算机能解读、运行的低阶机器语言的程序。编译器将原始程序作为输入,翻译产生使用目标语言的等价程序。源代码一般为高阶语言如Pascal、C++、Java 等,而目标语言则是汇编语言或目标机器的目标代码,有时也称作机器代码。 2.编译器的种类 编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高阶语言作为输入,输出也是高阶语言的编译器。例如: 自动并行化编译器经常采用一种高阶语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语

CMinus词法分析和语法分析设计编译器编译原理课程设计报告书

编译原理课程设计报告 课题名称:C- Minus词法分析和语法分析设计 提交文档学生姓名:X X X 提交文档学生学号:XXXXXXXXXX 同组成员名单:X X X 指导教师姓名:X X 指导教师评阅成绩: 指导教师评阅意见: . . 提交报告时间:2015年6月10日

1.课程设计目标 实验建立C-编译器。只含有扫描程序(scanner)和语法分析(parser)部分。 2.分析与设计 C-编译器设计的整体框架,本实验实现扫描处理和语法分析程序(图中粗黑部分)。 2.1 、扫描程序scanner部分 2.1.1系统设计思想 设计思想:根据DFA图用switch-case结构实现状态转换。 惯用词法:

①语言的关键字:else if int return void while ②专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */ ③其他标记是ID和NUM,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 大写和小写字母是有区别的 ④空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开ID、NUM 关键字。 ⑤注释用通常的C语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套 scanner的DFA

说明:当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。初始状态设置为START,当需要得到下一个token时,取得次token的第一个字符,并且按照DFA与对此字符的类型分析,转换状态。重复此步骤,直到DONE为止,输出token类型。当字符为“/”时,状态转换为SLAH再判断下一个字符,如果为“*”则继续转到INCOMMENT,最后以“*”时转到ENDCOMMENT状态,表明是注释,如果其他的则是字符停滞于当前字符,并且输出“/”。 2.1.2程序流程图

编译原理实验报告一

实验一词法分析程序实现 一、实验目得与要求 通过编写与调试一个词法分析程序,掌握在对程序设计语言得源程序进行扫描得过程中,将字符流形式得源程序转化为一个由各类单词符号组成得流得词法分析方法 二、实验内容 基本实验题目:若某一程序设计语言中得单词包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符与四个算术运算符,试构造能识别这些单词得词法分析程序(各类单词得分类码参见表I)。 表I语言中得各类单词符号及其分类码表 输入:由符合与不符合所规定得单词类别结构得各类单词组成得源程序文件。 输出:把所识别出得每一单词均按形如(CLASS,VALUE)得二元式形式输出,并将结果放到某个文件中。对于标识符与无符号常数,CLASS字段为相应得类别码得助记符;V AL UE字段则就是该标识符、常数得具体值;对于关键字与运算符,采用一词一类得编码形式,仅需在二元式得CLASS字段上放置相应单词得类别码得助记符,V ALUE字段则为“空". 三、实现方法与环境 词法分析就是编译程序得第一个处理阶段,可以通过两种途径来构造词法分析程序.其一就是根据对语言中各类单词得某种描述或定义(如BNF),用手工得方式(例如可用C语言)构造词法分析程序。一般地,可以根据文法或状态转换图构造相应得状态矩阵,该状态矩阵连同控制程序一起便组成了编译器得词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。构造词法分析程序得另外一种途径就是所谓得词法分析程序得自动生成,即首先用正规式对语言中得各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程

(重庆理工大学计算机学院)编译原理课程设计报告

编译原理课程设计报告 实验名称编译原理课程设计 班级 学号 姓名 指导教师 实验成绩 2013 年06月

一、实验目的 通过设计、编写和调试,将正规式转换为不确定的有穷自动机,再将不确定的有穷自动机转换为与之等价的确定的有穷自动机,最后再将确定有穷自动机进行简化。 通过设计、编写和调试构造LR(0)项目集规范簇和LR分析表、对给定的符号串进行LR分析的程序,了解构造LR(0)分析表的步骤,对文法的要求,能够从文法G出发生成LR(0)分析表,并对给定的符号串进行分析。 二、实验内容 正规式——>NFA——>DFA——>MFA 1.正规式转化为不确定的有穷自动机 (1)目的与要求 通过设计、编写和调试将正规式转换为不确定的有穷自动机的程序,使学生了解Thompson算法,掌握转换过程中的相关概念和方法,NFA的表现形式可以是表格或图形。 (2)问题描述 任意给定一个正规式r(包括连接、或、闭包运算),根据Thompson算法设计一个程序,生成与该正规式等价的NFA N。 (3)算法描述 对于Σ上的每个正规式R,可以构造一个Σ上的NFA M,使得L(M)=L(R)。 步骤1:首先构造基本符号的有穷自动机。 步骤2:其次构造连接、或和闭包运算的有穷自动机。

(4)基本要求 算法实现的基本要求是: (1) 输入一个正规式r; (2) 输出与正规式r等价的NFA。(5)测试数据 输入正规式:(a|b)*(aa|bb)(a|b)* 得到与之等价的NFA N

(6)输出结果 2.不确定的有穷自动机的确定化 (1)目的与要求 通过设计、编写和调试将不确定的有穷自动机转换为与之等价的确定的有穷自动机的程序,使学生了解子集法,掌握转换过程中的相关概念和方法。DFA的表现形式可以是表格或图形。(2)问题描述 任意给定一个不确定的有穷自动机N,根据算法设计一个程序,将该NFA N变换为与之等价的DFA D。 (3)算法描述 用子集法将NFA转换成接受同样语言的DFA。 步骤一:对状态图进行改造 (1) 增加状态X,Y,使之成为新的唯一的初态和终态。从X引ε弧到原初态结点, 从原终态结 点引ε弧到Y结点。 (2) 对状态图进一步进行如下形式的改变

编译原理课程设计

编译原理课程设计 自顶向下语法分析器 学院(系):计算机科学与技术学院学生姓名:xxxxxxxxx 学号:xxxxxxxxx 班级:电计1102 大连理工大学 Dalian University of Technology

目录

1 系统概论 语法分析是编译过程的核心部分。它的任务是在词法分析识别出单词符号串的基础上,分析并判定程序的语法结构是否符合语法规则。语法分析器在编译程序中的地位如图1所示: 图1 语法分析器在编译程序中的地位 语言的语法结构是用上下文无关文法描述的。因此,语法分析器的工作本质上就是按文法的产生式,识别输入符号串是否为一个句子。这里所说的输入串是指由单词符号(文法的终结符)组成的有限序列。对一个文法,当给你一串(终结)符号时,怎样知道它是不是该文法的一个句子呢?这就要判断,看是否能从文法的开始符号出发推导出这个输入串。或者,从概念上讲,就是要建立一棵与输入串相匹配的语法分析树。 自顶向下分析法就是语法分析办法中的一类。顾名思义,自顶向下就是从文法的开始符号出发,向下推导,推出句子。这种方法是带“回溯”的。 自顶向下分析的主旨是,对任何输入串,试图用一切可能的办法,从文法开始符号(根结)出发,自上而下地为输入串建立一棵语法树。或者说,为输入串寻找一个最左推导。这种分析过程本质上是一种试探过程,是反复使用不同产生式谋求匹配输入串的过程。 实现这种自顶向下的带回溯试探法的一个简单途径是让每个非终结符对应一个递归子程序。每个这种子程序可作为一个布尔过程。一旦发现它的某个候选与输入串相匹配,就用这个候选去扩展语法树,并返回“真”值;否则,保持原来的语法树和IP值不变,并返回“假”值。 2 需求分析 以前,人们对语法的分析都建立在人工的基础上,人工分析虽然能够做到侧类旁推,但终究人力有限,再精密的分析都会出现或多或少的错误。为减少因人为产生的错误,并加快

编译原理pL0实验报告

一.课程设计要求 基本内容: (1)扩充赋值运算:*= 和/= (2)扩充语句(Pascal的FOR语句): ①FOR <变量>:=<表达式> TO <表达式> DO <语句> ②FOR <变量>:=<表达式> DOWNTO <表达式> DO <语句> 其中,语句①的循环变量的步长为2, 语句②的循环变量的步长为-2。 二.设计思路 在课内实验的基础上,额外增加*=和/=运算符和关键字的语义动作,以下是设计思路: 1. 扩充单词 在头文件pl0.h中的enum symbol中增加关键字forsym, tosym, downtosym, timeseqlsym,slasheqlsym,并修改关键字数#define symnum 46。 /*初始化*/ // ssym['*=']=timeseql; // ssym['/=']=slasheql; /*设置保留字名字,按照字母顺序,便于折半查找*/ strcpy(&(word[14][0]),"to"); /*增加后需要按序排列*/ strcpy(&(word[7][0]),"for");

strcpy(&(word[4][0]),"downto"); strcpy(&(word[3][0]),"do"); /*设置保留字符号*/ wsym[7]=forsym; wsym[14]=tosym; /*语法分析,获取一个符号*/ 在getsym()部分添加: else if(ch=='*'){ /** “*=” **/ getchdo; if(ch=='='){ sym=timeseql; getchdo; printf("check *= success!"); } else sym=times; } else if(ch=='/'){ /* “/=” */ getchdo; if(ch=='='){sym=slasheql; getchdo; printf("check /= success!");

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

编译原理课程设计报告

2011-2012学年第二学期 《编译原理》课程设计报告 学院:计算机科学与工程学院 班级: 学生姓名:学号: 成绩: 指导教师: 时间:2012年5 月

目录 一、课程设计的目的 ---------------------------------------------------------------- - 1 - 二、课堂实验及课程设计的内容 -------------------------------------------------- - 1 - 2.1、课堂实验内容-------------------------------------------------------------- - 1 - 2.2、课程设计内容-------------------------------------------------------------- - 1 - 三、visual studio 2008 简介------------------------------------------------------- - 2 - 四、问题分析及相关原理介绍 ----------------------------------------------------- - 3 - 4.1、实验部分问题分析及相关原理介绍 ---------------------------------- - 3 - 4.1.1、词法分析功能介绍及分析------------------------------------- - 3 - 4.1.2、语法分析功能介绍及分析------------------------------------- - 3 - 4.1.3、语义分析功能介绍及分析------------------------------------- - 4 - 4.2、课程设计部分问题分析及相关原理介绍 ---------------------------- - 5 - 4.2.1、编译程序介绍 ----------------------------------------------------- - 5 - 4.2.2、对所写编译程序的源语言的描述(C语言) -------------- - 6 - 4.2.3、各部分的功能介绍及分析 -------------------------------------- - 7 - 4.3、关键算法:单词的识别-------------------------------------------------- - 8 - 4.3.1、算法思想介绍 ----------------------------------------------------- - 8 - 4.3.2、算法功能及分析 -------------------------------------------------- - 8 - 五、设计思路及关键问题的解决方法 ------------------------------------------ - 10 - 5.1、编译系统------------------------------------------------------------------ - 10 - 5.1.1、设计思路 --------------------------------------------------------- - 10 - 5.2、词法分析器总控算法--------------------------------------------------- - 12 - 5.2.1、设计思路 --------------------------------------------------------- - 12 - 5.2.2、关键问题及其解决方法 --------------------------------------- - 13 - 六、结果及测试分析-------------------------------------------------------------- - 14 - 6.1、软件运行环境及限制--------------------------------------------------- - 14 - 6.2、测试数据说明------------------------------------------------------------ - 14 - 6.3、运行结果及功能说明--------------------------------------------------- - 16 - 6.4、测试及分析说明--------------------------------------------------------- - 16 - 七、总结及心得体会 --------------------------------------------------------------- - 17 - 7.1、设计过程------------------------------------------------------------------ - 17 - 7.2、困难与收获 ------------------------------------------------------------- - 17 - 八、参考文献 ------------------------------------------------------------------------ - 18 -

编译原理课程设计

编译原理: 编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。编译原理是计算机专业设置的一门重要的专业课程。编译原理课程是计算机相关专业学生的必修课程和高等学校培养计算机专业人才的基础及核心课程,同时也是计算机专业课程中最难及最挑战学习能力的课程之一。编译原理课程内容主要是原理性质,高度抽象。 编译原理课程设计: 《编译原理课程设计》是2007年11月浙江大学出版社出版的图书,作者是冯雁、鲁东明、李莹。 内容简介: 本书围绕着编译技术的基本原理和方法,以模拟程序设计语言SPL的编译器的设计和实现为主线,结合词法分析、语法分析、语义分析、代码生成、代码优化、错误处理等各个基本模块,对原理和实现方法进行了详细分析。该编译器可接受SPL的程序,并将其翻译成汇编语言程序,最终实现汇编语言到8086/8088机器语言的翻译。本书为编译技术等相关课程的实验提供了参考。在附件中还提供了三类不同类型和难度的实验题,可供课程实验选择。 第1章引论: 1.1本书介绍 1.2SPL语言的特点及实验安排

1.2.1SPL语言的特点 1.2.2SPL语言编译器的主要结构1.2.3实验安排 1.3平台的选择和介绍 1.3.1LEX简介 1.3.2YACC简介 第2章词法分析: 2.1词法分析器的基本框架 2.2词法分析器的基本原理 2.2.1DFA的构造和实现 2.2.2词法分析的预处理 2.2.3实现词法分析器的注意要点2.3词法分析器的实现 2.3.1SPL语言单词属性字 2.3.2SPL词法分析器的输入和输出2.3.3SPL词法分析器的分析识别第3章语法分析: 3.1语法分析的基本框架 3.1.1上下文无关文法 3.1.2语法分析过程 3.1.3语法分析过程中的数据结构3.2语法分析的基本方法

编译原理课程设计

先简要分析一下语法分析的大致流程: 当有句子要进行处理时,首先要对其进行词法分析来分解出该句子中的每个符号,然后将该句子按照算符优先算法压入归约栈中,如果可以顺利归约,则说明这是一个合法的句子,否则该句子非法。 这里有一个需要考虑的地方,就是如何进行归约。由于文法已经给定,所以我们考虑设计一个文法表,文法表中的内容就是可归约串的种别码的顺序,比如v=E可以表示为9,1,13。这样的话当我们要进行一次归约时,只用按顺序存储最左素短语中符号的种别码,然后拿这个种别码序列与文法表进行匹配,就可知道当前归约需要执行哪些操作。 还有一点需要注意,就是如何对一个表达式进行求值。这里需要我们设计一个二元组的变量名表,这个变量名表可以根据变量的名称来返回变量的数据。变量名表的具体设计见详细设计部分。 由于是简化分析,所以这个程序只考虑整数的处理。 有了上面的分析,可以构造出算符优先分析算法的流程图,如下图所示。

详细设计 (1)词法分析部分 由于词法分析的内容在课程设计1中已经介绍,并且这次的状态转换图与课程设计1中的非常相似,所以这里就不过多介绍。(2)优先关系表 在程序中我们用一个二维数组priTable[][]来存储算符间的优先关系。priTable[a][b]=1表示a>b; 。priTable[a][b]=0表示a=b; 。priTable[a][b]=-1表示a

编译原理词法分析器

一、实验目的 了解词法分析程序的两种设计方法:1.根据状态转换图直接编程的方式;2.利用DFA 编写通用的词法分析程序。 二、实验内容及要求 1.根据状态转换图直接编程 编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法分析程序作为单独的一遍,如下图所示。 具体任务有: (1)组织源程序的输入 (2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件 (3)删除注释、空格和无用符号 (4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。将错误信息输出到屏幕上。 (5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。 标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址 注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。 常量表结构:常量名,常量值 2.编写DFA模拟程序 算法如下: DFA(S=S0,MOVE[][],F[],ALPHABET[]) /*S为状态,初值为DFA的初态,MOVE[][]为状态转换矩阵,F[] 为终态集,ALPHABET[] 为字母表,其中的字母顺序与MOVE[][] 中列标题的字母顺序一致。*/ { Char Wordbuffer[10]=“”//单词缓冲区置空 Nextchar=getchar();//读 i=0; while(nextchar!=NULL)//NULL代表此类单词 { if (nextcha r!∈ALPHABET[]){ERROR(“非法字符”),return(“非法字符”);} S=MOVE[S][nextchar] //下一状态 if(S=NULL)return(“不接受”);//下一状态为空,不能识别,单词错误 wordbuffer[i]=nextchar ;//保存单词符号 i++; nextchar=getchar(); } Wordbuffer[i]=‘\0’;

编译原理课程设计 C语言编译器的实现

编译原理课程设计报告 设计题目编译代码生成器设计 学生姓名 班级 学号 指导老师 成绩

一、课程设计的目的 编译原理课程兼有很强的理论性和实践性,是计算机专业的一门非常重要的专业基础课程,它在系统软件中占有十分重要的地位,是计算机专业学生的一门主修课。为了让学生能够更好地掌握编译原理的基本理论和编译程序构造的基本方法和技巧,融会贯通本课程所学专业理论知识,提高他们的软件设计能力,特设定该课程的课程设计,通过设计一个简单的PASCAL语言(EL语言)的编译程序,提高学生设计程序的能力,加深对编译理论知识的理解与应用。 二、课程设计的要求 1、明确课程设计任务,复习编译理论知识,查阅复印相关的编译资料。 2、按要求完成课程设计内容,课程设计报告要求文字和图表工整、思路清晰、算法正 确。 3、写出完整的算法框架。 4、编写完整的编译程序。 三、课程设计的内容 课程设计是一项综合性实践环节,是对平时实验的一个补充,课程设计内容包括课程的主要理论知识,但由于编译的知识量较复杂而且综合性较强,因而对一个完整的编译程序不适合平时实验。通过课程设计可以达到综合设计编译程序的目的。本课程的课程设计要求学生编写一个完整的编译程序,包括词法分析器、语法分析器以及实现对简单程序设计语言中的逻辑运算表达式、算术运算表达式、赋值语句、IF语句、While语句以及do…while语句进行编译,并生成中间代码和直接生汇编指令的代码生成器。 四、总体设计方案及详细设计 总体设计方案: 1.总体模块 主程序 词法分析程序语法分析 程序 中间代码 生成程序

2. 表2.1 各种单词符号对应的种别码 单词符号种别码单词符号种别码bgin 1 :17 If 2 := 18 Then 3 < 20 wile 4 <> 21 do 5 <= 22 end 6 > 23 lettet(letter|digit)* 10 >= 24 dight dight* 11 = 25 + 13 ;26 —14 ( 27 * 15 ) 28 / 16 # 0 详细设计: 4.1界面导入设计 (1)一共三个选项: ①choice 1--------cifafenxi ②choice 2--------yufafenxi ③choice 3--------zhongjiandaima (2)界面演示 图一

编译原理实验报告:实验一编写词法分析程序

( 编译原理实验报告 , 实验名称:实验一编写词法分析程序 实验类型:验证型实验 指导教师:何中胜 专业班级:( 13软件四 姓名:丁越 学号: 实验地点:) 秋白楼B720

实验成绩: 日期:2016年 3 月 18 日

一、实验目的 通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析程序所用的工具自动机,进一步理解自动机理论。掌握文法转换成自动机的技术及有穷自动机实现的方法。确定词法分析器的输出形式及标识符与关键字的区分方法。加深对课堂教学的理解;提高词法分析方法的实践能力。通过本实验,应达到以下目标:[ 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、实验过程 以编写PASCAL子集的词法分析程序为例 1.理论部分 > (1)主程序设计考虑 主程序的说明部分为各种表格和变量安排空间。 数组 k为关键字表,每个数组元素存放一个关键字。采用定长的方式,较短的关键字后面补空格。 P数组存放分界符。为了简单起见,分界符、算术运算符和关系运算符都放在 p表中(编程时,还应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。 id和ci数组分别存放标识符和常数。 instring数组为输入源程序的单词缓存。 ¥ outtoken记录为输出内部表示缓存。 还有一些为造表填表设置的变量。 主程序开始后,先以人工方式输入关键字,造 k表;再输入分界符等造p表。 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。 ⑵词法分析过程考虑 将词法分析程序设计成独立一遍扫描源程序的结构。其流程图见图 1-1。 …

编译原理词法分析实验报告

词法分析器实验报告 一、实验目的 选择一种编程语言实现简单的词法分析程序,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 二、实验要求 2、1 待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都就是小写。 (2)运算符与界符 : = + - * / < <= <> > >= = ; ( ) # (3)其她单词就是标识符(ID)与整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符与换行符组成。空格一般用来分隔ID、SUM、运算符、界符与关键字,词法分析阶段通常被忽略。 2、2 各种单词符号对应的种别码: 表2、1 各种单词符号对应的种别码 2、3 词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…… 三、词法分析程序的算法思想: 算法的基本任务就是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想就是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 3、1 主程序示意图:

主程序示意图如图3-1所示。其中初始包括以下两个方面: ⑴ 关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下: Char *rwtab[6] = {“begin ”, “if ”, “then ”, “while ”, “do ”, “end ”,}; (2)3、2 扫描子程序的算法思想: 首先设置3个变量:①token 用来存放构成单词符号的字符串;②sum 用来整型单词;③syn 用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。

相关文档
相关文档 最新文档