PL0语言的词法语法分析器的设计与实现.docx
- 文档编号:10045815
- 上传时间:2023-02-08
- 格式:DOCX
- 页数:33
- 大小:528.55KB
PL0语言的词法语法分析器的设计与实现.docx
《PL0语言的词法语法分析器的设计与实现.docx》由会员分享,可在线阅读,更多相关《PL0语言的词法语法分析器的设计与实现.docx(33页珍藏版)》请在冰豆网上搜索。
PL0语言的词法语法分析器的设计与实现
PL/0语言的词法语法分析器的设计与实现
摘要:
编译器是现代运算机系统的大体组成部份之一,它把源语言程序翻译成目口号言程序。
词法分析和语法分析是编译器的两个重要功能。
词法分析的任务是对组成源程序的字符流进行扫描和分解,从而识别出单词序列;语法分析的任务是将词法分析得到的单词序列分解成各类语法短语。
本文在介绍PL/0语言编译器的词法分析和语法分析进程的基础上,具体论述了利用VC++作为编程工具完成PL/0语言词法与语法分析器的设计与实现的进程。
关键词:
编译器;源语言;目口号言;词法分析;语法分析
DesigningandImplementingtheLexicalAnalyzerandSyntaxAnalyzerofPL/0Language
Abstract:
Compilerisabasicpartofmoderncomputersystem,ittranslatesthesourcelanguageprogramintothetargetlanguageanalysisandsyntaxanalysisaretwoimportantfunctionofthecompiler.Theformercompletesthetaskofscanninganddecomposingthestreamofcharactersmakingupthesourceprogramandidentifyingsequencesofwords.Thelattercompletesthetaskofclassingthestreamofwordsintosyntaxphrases.Inthispaper,onthebasisofintroducingthecoursesoflexicalanalysingandsyntaxanalyzingofofPL/0Languagecompiler,thedesignandimplementationprocessofusingVisualC++asaprogrammingtooltocompletethelexicalanalyzerandsyntaxanalyzerofPL/0Languageisconcretelydescribed.
Keywords:
Compiler;Sourcelanguage;Targetlanguage;Lexicalanalysis;Syntaxanalysis
1前言
编译器是现代运算机系统的大体组成部份之一,而且多数运算机系统都含有不止一个高级语言的编译器,对有些高级语言乃至配置了几个不同性能的编译器。
从功能上看,一个编译器确实是一个语言翻译程序。
它把一种语言(称作源语言)书写的程序翻译成另一种语言(称作目口号言)的等价的程序。
比如汇编程序是一个翻译程序,它把汇编语言程序翻译成机械语言程序。
若是源语言是像FORTRAN,PASCAL,或C那样的高级语言,目口号言是像汇编语言或机械语言那样的低级语言,那么这种翻译程序称作编译程序或编译器[3]。
词法分析是编译进程的第一个时期,那个时期的作用是从左到右一个字符一个字符地读入源程序,对组成源程序的字符流进行扫描和分解,从而识别一个个单词。
源程序中常见的单词能够归为几大类:
关键字、标识符、字面量和特殊符号。
语法分析确实是编译进程的第二个时期,它的作用是在词法分析的基础上将单词序列分解成各类语法短语,如“程序”,“语句”,“表达式”等等。
因此语法分析器的任务是在词法分析的基础上对源程序的语法短语进行分析,找出其中的错误而且对用户发出警告[5]。
文献[8]中指出,PL/0语言具有功能简单、结构清楚、可读性强的特点,且具有了一样高级语言的必需部份。
PL/0语言的编译器能充分表现一个高级语言编译器实现的大体技术和步骤。
因此,本次毕业设计在对PL/0语言编译器的词法分析进程与语法分析进程进行深切分析研究的基础上,采纳VC++编程来实现PL/0语言的词法与语法分析器。
以通过对PL/0语言编译器中的词法分析和语法分析程序的学习和词法语法分析器的设计,达到深切明白得编译原理及熟练把握编程语言的目的。
2PL/0语言描述
PL/0语言是PASCAL语言的一个子集[3],要紧用于处置整型数值间的加减乘除和赋值等各类简单运算和各种关系运算,它的功能简单、结构清楚、可读性强、而又具有了一样高级语言的必需部份,PL/0语言的编译器能充分表现一个高级语言编译器实现的大体技术和步骤,对成立实现编译器的整体概念有专门大帮忙。
以下为一个PL/0例如程序:
Programabc;/*以下是程序体*/
Varx,y,z;/*变量声明*/
Consta=10;/*常量声明*/
Procedureab(integerm,n:
Var;t:
Const);/*进程声明*/
Begin
t:
=n+m;
Ifm>nthen/*条件语句*/
n:
=t
else
m:
=t;
Whilen Begin n: =n+1 End End; Begin x: =1;y: =2;z: =3; Callab(x,y,z); z: =4+z+(1+2+6+x)*3*y*5+7; If~3<=x&y<>4thenz: =0;/*条件表达式*/ y: =219;z: =37;x: =a*z/*赋值语句*/ End ./*程序终止符*/ 依照例如程序能够看到PL/0语言鲜明的特点,为了更清楚的了解它的语法特点,下面别离用语法描述图和EBNF来表示。 PL/0语言的语法描述图 PL/0语言的语法规那么可用语法描述图来描述,用语法图描述语法规那么具有直观、易读的优势。 在语法图中,用椭圆和圆圈中的英文字表示终结符,用长方形内的中文字表示非终结符。 所谓终结符,是组成语言文法的单词,是语法成份的最小单位。 而每一个非终结符是一个语法成份,在书写语言程序时并非显现,它是由终结符和非终结符、或终结符串概念的[11]。 例如,图2-1中,程序是由非终结符‘分程序’和终结符“.”那个串概念的。 由于对某些非终结符能够递归概念,这就使得无穷的句子集可用有穷的文法描述。 而通常称第一个非终结符如‘程序’为文法的开始符号。 如图2-2所示为分程序的语法描述图。 分程序 . 程序 图2-1程序语法描述图 图2-2分程序语法描述图 PL/0语言文法的EBNF表示 PL/0语言的语法描述也可用扩充的巴科斯-瑙尔范式[3]表达如下: (1)EBNF表示的符号说明 <>: 用左右尖括号括起来的中文字表示语法构造成份,或称语法单位,为非终结符。 ‘: : =’: 该符号的左部由右部概念,可读作‘概念为’。 ‘|’: 表示‘或’,为左部可由多个右部概念。 ‘{}’: 表示花括号内的语法成份能够重复。 在不加上下界时可重复0到任意次数,在有上下界时为可重复次数的限制。 ‘[]’: 表示方括号内的成份为任选项。 ‘()’: 表示圆括号内的成份优先。 (2)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|9 3PL/0语言的词法与语法分析 PL/0编译器的词法分析 文献[12]中指出,PL/0编译器的词法分析程序能够看成是一个独立的进程,其功能是为语法分析提供单词,是语法分析的基础,它把输入的字符串形式的源程序分割成一个个单词符号。 为此PL/0编译器设置了三个全程量的公用单元如下: (1)SYM: 寄存每一个单词的类别,用内部编码形式表示。 (2)ID: 寄存用户所概念的标识符的值。 即标识符字符串的机内表示。 (3)NUM: 寄存用户自概念的数。 PL/0语言单词的种类有五种。 (1)大体字: 也可称为保留字,如BEGIN、END、IF、THEN等。 (2)运算符: 如+、-、*、/、: =、#、>=、<=等。 (3)标识符: 如用户概念的变量名、常数名、进程名。 (4)常数: 如10、25、100等整数。 (5)界符: 如‘、’、‘.’、‘;’、‘(’、‘)’等。 若是把大体字、运算符、界符称为语言固有的单词,而对标识符、常数称为用户概念的单词。 那么经词法分析程序分解出的单词,对语言固有的单词只给出类别寄存在SYM中,而对用户概念的单词(标识符或常数)既给出类别又给出值,其类别放在SYM中,值放在ID或NUM中,全数单词种类由编译器概念的SYMBOL给出,也可称为语法的辞汇表。 如下面提到的IFSYM,THENSYM,IDENT,NUMBER均属SYMBOL中的元素。 因此,PL/0编译器的词法分析进程将完成以下任务: (1)滤空格: 空格在词法分析时是一种不可缺少的界符,而在语法分析时那么是无用的因此必需滤掉。 (2)识别保留字: 设有一张保留表。 对每一个字母打头的字母、数字字符串要查此表。 假设查着那么为保留字,将对应的类别放在SYM中。 如IF对应值IFSYM,THEN对应值THENSYM。 假设查不到,那么以为是用户概念的标识符。 (3)识别标识符: 对用户概念的标识符将IDENT放在SYM中,标识符本身的值放在ID中。 (4)拼数: 当所取单词是数字时,将数的类别NUMBER放在SYM中,数值本身的值寄存在NUM中。 (5)拼复合词: 对两个字符组成的算符如: >=、: =、<=等单词,识别后将类别送SYM中。 (6)输出源程序: 为边读入字符边输出(可输出在文件中)。 由于一个单词往往是由一个或几个字符组成的,因此在词法分析进程CIFAFENXI中又概念了一个取字符进程GETCH,由词法分析需要取字符时挪用。 依照以上分析,可得词法分析进程CIFAFENXI的流程图如图3-1所示。 图3-1词法分析进程CIFAFENXI 取字符进程GETCH的流程图如图3-2所示。 图3-2取字符进程GETCH 图中GETCH所用单元说明如下: CH: 寄存当前读取的字符,初值为空。 LINE: 为一维数组,其数组元素为字符,界对为1: 80。 用于读入一行字符的缓冲区。 LL和CC为计数器,初值为0。 CIFAFENXI流程图的工作单元说明: A: 一维数组,数组元素为字符,界对[1: 10]。 ID: 同A。 WORD: 保留字表,一维数组,数组元素是以字符为元素的一维数组。 界对为[1: 13]。 查表采纳二分法。 依照上述描述概念一个词法分析子程序,命名为getsym,其功能是从源程序中读出一个单词符号(token),把它的信息放入全局变量sym、id和num中,语法分析器需要单词时,直接从这三个变量中取得。 (注意! 语法分析器每次用完这三个变量的值就当即挪用getsym子程序获取新的单词供下一次利用。 而不是在需要新单词时才挪用getsym进程。 )getsym进程通过反复挪用getch子进程从源程序过获取字符,并把它们拼成单词。 getch进程中利用了行缓冲区技术以提高程序运行效率。 挪用getsym时,它通过getch进程从源程序中取得一个字符。 若是那个字符是字母,那么继续获取字符或数字,最终能够拼成一个单词,查保留字表,若是查到为保留字,那么把sym变量赋成相应的保留字类型值;若是没有查到,那么那个单词应是一个用户自概念的标识符(可能是变量名、常量名或是进程的名字),把sym置为ident,把那个单词存入id变量。 查保留字表时利用了二分法查找以提高效率。 若是getch取得的字符是数字,那么继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。 若是识别出其它合法的符号(比如: 赋值号、大于号、小于等于号等),那么把sym置成相应的类型。 若是碰到不合法的字符,把sym置成null。 PL/0编译器的语法分析 文献[12]中指出,语法分析的任务是识别由词法分析给出的单词符号序列在结构上是不是符合给定的文法规那么。 PL/0语言的文法规那么已在前面给出,本节将以语法图描述的语法形式为依据,给出语法分析的直观思想。 PL/0编译器语法分析进程的直观思想 PL/0编译器的语法分析采纳了自顶向下的递归子程序法[3]。 粗略地说,确实是对应每一个非终结符语法单元,编一个独立的处置进程(或子程序)。 语法分析从读入第一个单词开始由非终结符‘程序’即开始符动身,沿语法描述图箭头所指出的方向进行分析,当碰到非终结符时,那么挪用相应的处置进程,从语法描述图看,也就是进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当碰到描述图中是终结符时,那么判定当前读入的单词是不是与图中的终结符相匹配,假设匹配那么说明符合语法规那么;再读取下一个单词继续分析。 碰到分支点时将当前的单词与分支点上的多个终结符逐个相较较,假设都不匹配时可能是进入下一非终结符语法单位或是犯错。 文献[8]中指出,若是一个PL/0语言的单词序列在整个语法分析中,都能逐个取得匹配,直到终止符‘.’,这时说明所输入的程序是正确的。 图3-3语法调用关系 程序 分程序 语句 条件 表达式 项 因子 以上所述语法分析进程超级直观粗浅,事实上应用递归子程序法构造语法分析程序时,要求文法必需是LL (1)文法[3]。 一个LL (1)文法是无二义性的,它具有以下两个特点: (1)每一个产生式的右部都由终结符号开始。 (2)若是两个产生式有相同的左部,那么它们的右部 由不同的终结符开始。 关于如此的文法显然在推导进程中完全能够依照当前的 输入符号决定选择哪个产生式往下推导,因此分析进程 是唯一确信的。 另外,从PL/0的语法描述图中能够清楚的看到,当 对PL/0语言进行语法分析时,各个非终结符语法单元所 对应的分析进程之间必需存在彼此挪用的关系。 这种挪用 关系可用图3-3表示。 也可称为PL/0语法的依托图,在图 中箭头所指向的程序单元表示存在挪用关系,从图中不难 看出这些子程序在语法分析时被直接挪用或间接递归挪用。 PL/0编译器语法分析程序分析 语法分析要紧完成两大功能: 说明部份的处置和程序体的处置[3]。 程序体确实是语法单元中的分程序部份,通常把它称为进程体。 语法分析由进程YUFAFENXI完成,其流程如图3-4所示。 YUFAFENXI 为DX,TX置初值,暂时保留CODE的下标指针CX值在TABLE表中 SYM=CONSTSYM? 常量说明处理 SYM=VARSYM? 变量说明处理 SYM=PROCSYM? 在TABLE表中登记过程名 递归调用YUFAFENXI CIFAFENXI 出错处理 返回 是否为语句开始符 在TABLE表中返填过程体入口 图3-4YUFAFENXI进程的流程图 进程YUFAFENXI内对程序说明部份和程序体部份的处置如下: (1)说明部份 由于PL/0语言许诺进程挪用语句,且许诺进程嵌套概念,因此每一个进程应有进程首部以概念局部于它自己进程的常量、变量、和进程标识符,也称局部量[3]。 每一个进程所概念的局部量只能供它自己和它自己概念的内进程引用。 关于同一层并列进程的挪用关系是先概念者能够被后概念者引用,反之那么不行。 说明部份的处置任务确实是对每一个进程(包括主程序,也可看成是一个主进程)的说明对象造名字表,填写所在层次(主程序为第0层,主程序概念的进程为第1层,随着嵌套的深度增加而将层次数加大。 PL/0最多许诺3层)、标识符的属性和分派的相对 位置等。 标识符的属性不同时,所需要填的信息也不同。 不同的信息是挪用不同的进程完成的。 所造表放在全程量一维数组TABLE表中。 TX为索引表的指针,表中的每一个元素为纪录型数据。 LEV给出层次,DX给出每层局部量当前分派到的相对位置,可称地址指示器,每说明完一个变量后DX指示器加1。 例如: 一个进程的说明部份为: CONSTA=35,B=49; VARC,D,E; PRTCEDUREP; VARG 对它的常量,变量和进程名说明分析后,在TABLE表中的信息如表3-1所示。 表3-1TABLE表的信息 NAME: A NAME: B NAME: C NAME: D NAME: E NAME: P KIND: CONSTANT KIND: CONSTANT KIND: VARIABLE KIND: VARIABLE KIND: VARIABLE KIND: PROCEDUR VAL: 35 VAL: 49 LEVEL: LEV LEVEL: LEV LEVEL: LEV LEVEL: LEV ADR: DX ADR: DX+1 ADR: DX+2 ADR: NAME: G … KIND: VARIABLE … LEVEL: LEV+1 … ADR: DX … 在说明处置后TABLE表中的信息关于进程名的ADR域,是在进程体的目标代码生成后返填进程体的入口地址。 例中在处置P进程的说明时对LEV就增加1。 在P进程中的变量名的层次为LEV+1后的值。 对进程还有一项数据SIZE,是记录该进程所需的数据空间。 TABLE表的表头索引TX和层次单元LEV都以YUFAFENXI的参数形式显现。 在主程序挪用YUFAFENXI时实参值都为0.每一个进程中的变量的相对起始位置在YUFAFENXI内置初值DX: =3。 (2)进程体 程序的主体是由语句[12]组成的。 处置完进程的说明后就处置由语句组成的进程体,从语法上要对语句进行逐句分析。 当语法正确时就打印程序正确。 当碰到标识符的引历时就查TABLE表,看是不是有过正确的概念,假设已有,那么从表中取相应的有关信息,供代码的生成用,假设无概念那么犯错。 4PL/0语言词法与语法分析器的设计 文献[9]中指出,为了方便程序的编写,一样软件的开发都将开发工作分成假设干个功能模块。 本分析器的功能设计模块计划如图4-1所示。 本分析器将软件中显现次数比较频繁的一些经常使用代码设计为独立的单元,例如设置颜色的代码和词法分析和语法分析的代码等,如此设计新的模块时若是有重复显现的部份,只需要将编写好的模块用include语句[9]来组装就能够够了。 本分析器尽管分为宜几个模块来设计,可是它们的功能是独立的,能够分开来设计和编写,如此有利于提高模块的内聚性[3],降低了程序的耦合性[3]。 词法语法分析器 窗口的初始化 菜单的设计 工具条的设计 弹出式对话框设计 添加语法分析 添加词法分析 添加样例演示 添加设置颜色 图标按钮化 24位位图设计 关于此分析器 颜色设置框 窗口切割设计 起始屏的设计 词法语法分析 图4-1分析器的设计模块图 5PL/0语言词法与语法分析器的编程实现 编程环境简介 依照开发本分析器所利用的开发工具的特点,出于平安性考虑,开发本词法与语法分析器软件时,对软件环境和硬件环境有特定的要求。 系统硬件设备 本软件开发时需要具有PentiumIII处置器且知足以下要求的运算机: 最低256MB内存、最小8G硬盘、鼠标、键盘。 系统支持软件 本软件在WindowsXP操作系统上开发。 所用的开发工具包是MicrosoftVisualStudio2005或VC++。 VisualC++是聚集了MS公司技术精华的主流产品,它将程序设计方式与可视的软件开发环境完美地结合在一路,其开发环境和适应Internet应用程序的特点很适合于开发Windows应用程序,因此受到广大软件设计人员的青睐。 利用VisualC++能够开发壮大的32位应用程序,能为用户全方位地效劳[1]。 所采纳的关键技术介绍 由于采纳的是VisualC++进行本词法与语法分析器的编写,因此依如实际需要,开发该词法与语法分析器时用到的关键技术要紧有窗口初始化、切分窗口、和位图显示技术。 窗口初始化 在开发VC++应用程序时,MicroSoft公司提供了一种被称为AppWizard的动态模板生成程序[1]。 创建的步骤如下: (1)成立Application MicroSoftVisualC++编译器的菜单条中,选择File菜单,然后从列出的菜单项当选择“New”按钮,创建一个MFCAppWizard(exe)的应用程序,为本分析器的工程命名为“SS”,如图5-1所示。 (2)生成代码及资源视图 单击“OK”,选择“Singledocument”和依次点击“Next>”直到所有设置初始化以后单击“Finish”按钮,将会看到一个对话框是AppWizard为那个项目创建的东西的简单描述,它是对各项选择的一个摘要。 接着单击“OK”就能够够生成如图5-2所示的关于那个窗口的代码和资源视图。 图5-1工程的创建视图 图5-2分析器的设计资源视图 切分窗口 因为所开发的词法语法分析器既有输入程序又要求将分析结果输出在窗口中,因此为了区分输入与输出,必需实现两个窗口的并列显示,于是用到了切分窗口技术,在拆分窗口中,窗口能够被拆分成多个面板,多个面板能够相关于一个视图,也能够一一对应视图。 在窗口拆分中可分为静态窗口拆分和动态窗口拆分[1],能够用CSplitterWnd类来实现这两种类型的窗口拆分,既能够将窗口纵向拆分,也能够横向拆分。 动态拆分窗口能够被拆分成多个面板,如此,当用户想同时阅读同一文档中的两个不同位置的内容时,没必要打开两个窗口,而直接将该文档分成假设干个窗口即可。 静态拆分窗口能够被拆分成多个面板的窗口,而每一个面板起到不同的作用,因此依如实际需要那个地址采纳了静态拆分窗口技术。 在主界面中嵌入CSplitterWnd成员变量时,利用CreatStatic()函数进行创建,其原型为: BOOLCreatStatic(CWnd*pPare
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- PL0 语言 词法 语法 分析器 设计 实现