您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 市场营销 > COMPILER-PL0语言的示例-语法描述
1补充: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,if-then,do,while,call,begin-end,赋值语句)PL/0语言中的数据类型只有整型,没有浮点数,所以圆周率只能近似为3。数字最多为14位。标识符的有效长度是10PL/0语言允许过程嵌套定义和递归调用的。过程最多可嵌套三层。过程可以引用自己定义的局部标识符,也可以引用包围在它的外过程(包括主程序)定义的标识符。2以下将用扩充的巴科斯-瑙尔范式(BACKUS-NAURFORM)和语法图(EBNF)两种形式给出PL/0语言的语法描述。-------------------------------------------------------------------------------------------------------------------------------------------------------(a)PL/0语言文法的EBNF表示EBNF表示的符号说明1)〈〉:用左右尖括号括起来的中文字表示语法构造成分,或称语法单位,为非终结符。2)∷=:该符号的左部由右部定义,可读作'定义为'。3)|:表示'或',为左部可由多个右部定义。标识符|常量是不允许的.因为非终结符作为一个独立的单位,不可分割4){}:花括号表示其内的语法成分可以重复。在不加上下界时可重复0到任意次数,有上下界时为可重复次数的限制。如:{*}表示*重复任意次,{*}38表示*重复3-8次。例如标识符::=l{l|d}09表示标识符的长度小于等于10.5)[]:方括号表示其内的成分为任选项。6)():表示圆括号内的成分优先。PL/0语言文法的EBNF表示为:〈程序〉∷=〈分程序〉.〈分程序〉∷=[〈常量说明部分〉][〈变量说明部分〉][〈过程说明部分〉]〈语句〉〈常量说明部分〉∷=CONST〈常量定义〉{,〈常量定义〉};〈常量定义〉∷=〈标识符〉=〈无符号整数〉〈无符号整数〉∷=〈数字〉{〈数字〉}〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉};〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};〈过程首部〉∷=PROCEDURE〈标识符〉;〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈当型循环语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉〈赋值语句〉∷=〈标识符〉∶=〈表达式〉〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉|ODD〈表达式〉〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉〈项〉}〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'〈加法运算符〉∷=+|-〈乘法运算符〉∷=*|/〈关系运算符〉∷=#|=|<|<=|>|>=〈条件语句〉∷=IF〈条件〉THEN〈语句〉〈过程调用语句〉∷=CALL〈标识符〉〈当型循环语句〉∷=WHILE〈条件〉DO〈语句〉〈读语句〉∷=READ'('〈标识符〉{,〈标识符〉}')'〈写语句〉∷=WRITE'('〈表达式〉{,〈表达式〉}')'〈字母〉∷=a|b|…|X|Y|Z〈数字〉∷=0|1|2|…|8|93(b)PL/0语言的语法描述图用椭圆和圆圈中的英文字表示终结符,用长方形内的中文字表示非终结符。画语法图时要注意箭头方向和弧度,语法图中应该无直角,如图2.1给出的PL/0语法描述图。沿语法图分析时不能走尖狐线。图2.1(a)程序语法描述图p9图2.1(b)分程序语法描述图p10按照上图,不能将常量定义写在变量定义前面.内的文字表示非终结符或内的文字或符号表示终结符4图2.1(c)语句语法描述图可以改动上图,增加else语句可以改动上图,使do语句可以处理多条语句.图2.1(d)条件语法描述图条件ifthen语句else语句语句do,5图2.1(e)表达式语法描述图图2.1(f)项语法描述图图2.1(g)因子语法描述图6附录:源代码pl0c.h/*关键字个数*/#definenorw13/*名字表容量*/#definetxmax100/*所有的add1用于定义数组*/#definetxmaxadd1101/*number的最大位数*/#definenmax14/*符号的最大长度*/#defineal10/*地址上界*/#defineamax2047/*最大允许过程嵌套声明层数*/#definelevmax3/*最多的虚拟机代码数*/#definecxmax200#definecxmaxadd1201/*当函数中会发生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-1typedefenum{false,true}bool;/*符号*/enumsymbol{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};#definesymnum32/*名字表中的类型*/enumobject{constant,variable,procedur};/*虚拟机代码*/enumfct{lit,opr,lod,sto,cal,inte,jmp,jpc};#definefctnum87/*虚拟机代码结构*/structinstruction{enumfctf;/*虚拟机代码指令*/intl;/*引用层与声明层的层次差*/inta;/*根据f的不同而不同*/};FILE*fas;/*输出名字表*/FILE*fa;/*输出虚拟机代码*/FILE*fa1;/*输出源文件及其各行对应的首地址*/FILE*fa2;/*输出结果*/boollistswitch;/*显示虚拟机代码与否*/booltableswitch;/*显示名字表与否*/charch;/*获取字符的缓冲区,getch使用*/enumsymbolsym;/*当前的符号*/charid[al];/*当前ident*/intnum;/*当前number*/intcc,ll,kk;/*getch使用的计数器,cc表示当前字符(ch)的位置*/intcx;/*虚拟机代码指针*/charline[81];/*读取行缓冲区*/chara[al];/*临时符号*/structinstructioncode[cxmaxadd1];/*存放虚拟机代码的数组*/charword[norw][al];/*保留字*/enumsymbolwsym[norw];/*保留字对应的符号值*/enumsymbolssym[256];/*单字符的符号值*/charmnemonic[fctnum][5];/*虚拟机代码指令名称*/booldeclbegsys[symnum];/*表示声明开始的符号集合*/boolstatbegsys[symnum];/*表示语句开始的符号集合*/boolfacbegsys[symnum];/*表示因子开始的符号集合*//*名字表结构*/structtablestruct{charname[al];/*名字*/enumobjectkind;/*类型:const,varorprocedure*/intval;/*数值,仅const使用*/intlevel;/*所处层,仅const不使用*/intadr;/*地址,仅const不使用*/intsize;/*需要分配的数据区空间,仅procedure使用*/};structtablestructtable[txmaxadd1];/*名字表*/FILE*fin;FILE*fout;charfname[al];interr;/*错误计数器*/8voiderror(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);intpostion(char*idt,inttx);voidenter(enumobjectk,int*ptx,intlev,int*pdx);intbase(intl,int*s,intb);pl0c.c/*Windows下c语言PL/0编译程序在VisualC++6.0和VisualC.NET上运行通过使用方法:运行后输入PL/0源程序文件名回答是否输出虚拟机代码回答是否输出名字表fa.tmp输出虚拟机代码fa1.tmp输出源文件及其各行对应的首地址fa2.tm
本文标题:COMPILER-PL0语言的示例-语法描述
链接地址:https://www.777doc.com/doc-5524093 .html