ImageVerifierCode 换一换
格式:DOCX , 页数:54 ,大小:383.66KB ,
资源ID:27523241      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/27523241.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(COMPILERPL0语言的示例语法描述.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

COMPILERPL0语言的示例语法描述.docx

1、COMPILERPL0语言的示例语法描述补充: PL/0语言及其编译程序的实现1概述 PL/0语言的编译程序把PL/0语言程序翻译成为一种称为 类pcode的假想的栈式计算机汇编语言程序。这种汇编语言与机器无关,若要在某一机器上实现PL/0语言程序,只需用机器上配置的任何语言对类pcode语言程序进行解释执行。 世界著名计算机科学家N.Wirth编写了 PL/0语言的编译程序。 后面附了PL/0编译程序源代码。 2. PL/0语言描述 何为PL/0语言 PL/0语言是PASCAL语言的子集. 具备了一般高级语言的必备部分. (如: read,write,ifthen,do,while,call

2、,beginend,赋值语句) PL/0语言中的数据类型只有整型,没有浮点数,所以圆周率只能近似为3。数字最多为14位。标识符的有效长度是10 PL/0语言允许过程嵌套定义和递归调用的。过程最多可嵌套三层。 过程可以引用自己定义的局部标识符,也可以引用包围在它的外过程(包括主程序)定义的标识符。以下将用 扩充的巴科斯-瑙尔范式(BACKUS-NAUR FORM)和 语法图 (EBNF)两种形式给出PL/0语言的语法描述。-(a) PL/0语言文法的EBNF表示 EBNF表示的符号说明1) :用左右尖括号括起来的中文字表示语法构造成分,或称语法单位,为非终结符。2) = :该符号的左部由右部定义

3、,可读作定义为。3) | :表示或,为左部可由多个右部定义。 是不允许的. 因为非终结符作为一个独立的单位,不可分割4) :花括号表示其内的语法成分可以重复。在不加上下界时可重复0到任意次数,有上下界时为可重复次数的限制。 如:*表示*重复任意次,*38表示*重复3-8次。例如:= ll|d09 表示标识符的长度小于等于10.5) :方括号表示其内的成分为任选项。6) ( ) :表示圆括号内的成分优先。 PL/0语言文法的EBNF表示为:程序=分程序分程序=常量说明部分变量说明部分过程说明部分语句常量说明部分=CONST常量定义 ,常量定义;常量定义=标识符=无符号整数无符号整数=数字数字变量

4、说明部分=VAR标识符,标识符;标识符=字母字母|数字过程说明部分=过程首部分程序;过程说明部分;过程首部=PROCEDURE标识符;语句=赋值语句|条件语句|当型循环语句| 过程调用语句|读语句|写语句|复合语句|空赋值语句=标识符=表达式复合语句=BEGIN语句;语句END条件=表达式关系运算符表达式|ODD表达式表达式=+|-项加法运算符项 项=因子乘法运算符因子因子=标识符|无符号整数|(表达式)加法运算符=+|-乘法运算符=*|/关系运算符=#|=|=|=条件语句=IF条件THEN语句过程调用语句=CALL标识符当型循环语句=WHILE条件DO语句读语句=READ(标识符,标识符)写

5、语句=WRITE(表达式,表达式)字母=a|b|X|Y|Z数字=0|1|2|8|9(b) PL/0语言的语法描述图 用椭圆和圆圈中的英文字表示终结符,用长方形内的中文字表示非终结符。 画语法图时要注意箭头方向和弧度,语法图中应该无直角,如图 2.1给出的PL/0语法描述图。沿语法图分析时不能走尖狐线。图 2.1(a) 程序语法描述图 p9图 2.1(b) 分程序语法描述图 p10按照上图,不能将常量定义写在变量定义前面.图2.1(c) 语句语法描述图可以改动上图, 增加else语句可以改动上图, 使do语句可以处理多条语句.图 2.1(d) 条件语法描述图图 2.1(e) 表达式语法描述图图

6、2.1(f) 项语法描述图图 2.1(g) 因子语法描述图附录: 源代码pl0c.h/* 关键字个数 */#define norw 13/* 名字表容量 */#define txmax 100/* 所有的add1用于定义数组 */#define txmaxadd1 101/* number的最大位数 */#define nmax 14/* 符号的最大长度 */#define al 10/* 地址上界 */#define amax 2047/* 最大允许过程嵌套声明层数 */#define levmax 3/* 最多的虚拟机代码数 */#define cxmax 200#define cxmax

7、add1 201/* 当函数中会发生fatal error时,返回-1告知调用它的函数,最终退出程序 */#define getsymdo if(-1=getsym()return -1#define getchdo if(-1=getch()return -1#define testdo(a,b,c) if(-1=test(a,b,c)return -1#define gendo(a,b,c) if(-1=gen(a,b,c)return -1#define expressiondo(a,b,c) if(-1=expression(a,b,c)return -1#define factord

8、o(a,b,c) if(-1=factor(a,b,c)return -1#define termdo(a,b,c) if(-1=term(a,b,c)return -1#define conditiondo(a,b,c) if(-1=condition(a,b,c)return -1#define statementdo(a,b,c) if(-1=statement(a,b,c)return -1#define constdeclarationdo(a,b,c) if(-1=constdeclaration(a,b,c)return -1#define vardeclarationdo(a,

9、b,c) if(-1=vardeclaration(a,b,c)return -1typedef enum false,true bool;/* 符号 */enum symbol nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,rparen,comma,semicolon,period,becomes,beginsym,endsym,ifsym,thensym,whilesym,writesym,readsym,dosym,callsym,constsym,varsym,procsym;

10、#define symnum 32/* 名字表中的类型 */enum object constant,variable,procedur;/* 虚拟机代码 */enum fct lit,opr,lod,sto,cal,inte,jmp,jpc;#define fctnum 8/* 虚拟机代码结构 */struct instruction enum fct f; /* 虚拟机代码指令 */ int l; /* 引用层与声明层的层次差 */ int a; /* 根据f的不同而不同 */;FILE* fas; /* 输出名字表 */FILE* fa; /* 输出虚拟机代码 */FILE* fa1;

11、/* 输出源文件及其各行对应的首地址 */FILE* fa2; /* 输出结果 */bool listswitch; /* 显示虚拟机代码与否 */bool tableswitch; /* 显示名字表与否 */char ch; /* 获取字符的缓冲区,getch 使用 */enum symbol sym; /* 当前的符号 */char idal; /* 当前ident */int num; /* 当前number */int cc,ll,kk; /* getch使用的计数器,cc表示当前字符(ch)的位置 */int cx; /* 虚拟机代码指针 */char line81; /* 读取行缓

12、冲区 */char aal; /* 临时符号 */struct instruction codecxmaxadd1; /* 存放虚拟机代码的数组 */char wordnorwal; /* 保留字 */enum symbol wsymnorw; /* 保留字对应的符号值 */enum symbol ssym256; /* 单字符的符号值 */char mnemonicfctnum5; /* 虚拟机代码指令名称 */bool declbegsyssymnum; /* 表示声明开始的符号集合 */bool statbegsyssymnum; /* 表示语句开始的符号集合 */bool facbeg

13、syssymnum; /* 表示因子开始的符号集合 */* 名字表结构 */struct tablestruct char nameal; /* 名字 */ enum object kind; /* 类型:const,var or procedure */ int val; /* 数值,仅const使用 */ int level; /* 所处层,仅const不使用 */ int adr; /* 地址,仅const不使用 */ int size; /* 需要分配的数据区空间,仅procedure使用 */;struct tablestruct tabletxmaxadd1; /* 名字表 */F

14、ILE* fin;FILE* fout;char fnameal;int err; /* 错误计数器 */void error(int n); int getsym();int getch();void init();int gen(enum fct x,int y,int z);int test(bool* s1,bool* s2,int n);int inset(int e,bool* s);int addset(bool* sr,bool* s1,bool* s2,int n);int subset(bool* sr,bool* s1,bool* s2,int n);int mulset

15、(bool* sr,bool* s1,bool* s2,int n);int block(int lev,int tx,bool* fsys);void interpret();int factor(bool* fsys,int* ptx,int lev);int term(bool* fsys,int* ptx,int lev);int condition(bool* fsys,int* ptx,int lev);int expression(bool* fsys,int* ptx,int lev);int statement(bool* fsys,int* ptx,int lev);voi

16、d listcode(int cx0);int vardeclaration(int* ptx,int lev,int* pdx);int constdeclaration(int* ptx,int lev,int* pdx);int postion(char* idt,int tx);void enter(enum object k,int* ptx,int lev,int* pdx);int base(int l,int* s,int b);pl0c.c/* Windows 下c语言PL/0编译程序在Visual C+ 6.0和Visual C.NET上运行通过使用方法:运行后输入PL/0

17、源程序文件名回答是否输出虚拟机代码回答是否输出名字表fa.tmp输出虚拟机代码fa1.tmp输出源文件及其各行对应的首地址fa2.tmp输出结果fas.tmp输出名字表*/#include #include pl0c.h#include string.h/* 解释执行时使用的栈 */#define stacksize 500 int main() bool nxtlevsymnum; init(); /* 初始化 */ fas=fopen(fas.tmp,w); fa1=fopen(fa1.tmp,w); printf(Input file? ); fprintf(fa1,Input file

18、? ); scanf(%s,fname); /* 输入文件名 */ fin=fopen(fname,r); if(fin) fprintf(fa1,%sn,fname); printf(List object code?(Y/N); /* 是否输出虚拟机代码 */ scanf(%s,fname); listswitch=(fname0=y|fname0=Y); printf(List symbol table?(Y/N); /* 是否输出名字表 */ scanf(%s,fname); tableswitch=(fname0=y|fname0=Y); err=0; cc=cx=ll=0; ch=

19、 ; kk=al-1; if(-1!=getsym() fa=fopen(fa.tmp,w); fa2=fopen(fa2.tmp,w); addset(nxtlev,declbegsys,statbegsys,symnum); nxtlevperiod=true; if(-1=block(0,0,nxtlev) /* 调用编译程序 */ fclose(fa); fclose(fa1); fclose(fin); printf(n); return 0; fclose(fa); fclose(fa1); if(sym!=period)error(9); if(err=0)interpret()

20、; /* 调用解释执行程序 */ else printf(Errors in pl/0 program); fclose(fin); else printf(Cant open file!n); fprintf(fa1,Cant open file!n); fclose(fa1); fclose(fas); printf(n); return 0;/* 在适当的位置显示错误 */void error(int n) char space81; memset(space,32,81); spacecc-1=0; /* 出错时当前符号已经读完,所以cc-1 */ printf(*%s!%dn,spa

21、ce,n); fprintf(fa1,*%s!%dn,space,n); err+;/* 词法分析,获取一个符号 */int getsym() int i,j,k; while(ch= |ch=10|ch=9) /* 忽略空格、换行和TAB */ getchdo; if(ch=a&ch=z) /* 名字或保留字以a.z开头 */ k=0; do if(k=a&ch=0&ch=9); ak=0; strcpy(id,a); i=0; j=norw-1; do /* 搜索当前符号是否为保留字 */ k=(i+j)/2; if(strcmp(id,wordk)=0)i=k+1; while(ij)s

22、ym=wsymk; else sym=ident; /* 搜索失败则,是名字或数字 */ else if(ch=0&ch=0&chnmax)error(30); else if(ch=:) /* 检测赋值符号 */ getchdo; if(ch=) sym=becomes; getchdo; else sym=nul; /* 不能识别的符号 */ else if(ch=) /* 检测大于或大于等于符号 */ getchdo; if(ch=) sym=geq; getchdo; else sym=gtr; else sym=ssymch; /* 当符号不满足上述条件时,全部按照单字符符号处理 *

23、/ getchdo; return 0;/* 生成虚拟机代码 */int gen(enum fct x, /* f */ int y, /* l */ int z /* a */ ) if(cxcxmax) printf(Program too long); /* 程序过长 */ return -1; codecx.f=x; codecx.l=y; codecx.a=z; cx+; return 0;/* 在某一部分(如一条语句,一个表达式)将要结束时时我们希望下一个符号属于某集合(该部分的后跟符号),test负责这项监测,并且负责当监测不通过时的补救措施,程序在需要检测时指定当前需要的符号集

24、合和补救用的集合(如之前未完成部分的后跟符号),以及检测不通过时的错误号 */int test(bool* s1, /* 我们需要的符号 */ bool* s2, /* 如果不是我们需要的,则需要一个补救用的集合 */ int n) /* 错误号 */ if(!inset(sym,s1) error(n); /* 当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合 */ while(!inset(sym,s1)&(!inset(sym,s2) getsymdo; return 0;/* 编译程序主体 */int block(int lev, /* 当前分程序所在层 */ int t

25、x, /* 名字表当前尾指针 */ bool* fsys /* 当前模块后跟符号集合 */ ) int i; int dx; /* 名字分配到的相对地址 */ int tx0; /* 保留初始tx */ int cx0; /* 保留初始cx */ bool nxtlevsymnum; /* 在下级函数的参数中,符号集合均为值参,但由于使用数租实现, 传递进来的是指针,为防止下级函数改变上级函数的集合,开辟新的空间 传递给下级函数,之后所有的nxtlev都是这样 */ dx=3; tx0=tx; /* 记录本层名字的初始位置 */ tabletx.adr=cx; gendo(jmp,0,0); if(levlevmax)error(32);

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

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