华北电力大学编译技术课程设计实验报告+代码

一、课程设计(综合实验)的目的与要求

通过设计、编写和调试词法分析程序,了解词法扫描器的组成结构、不同种类单词的识别方法,掌握由单词的词法规则出发,利用程序实现词法扫描器的方法。通过设计、编写和调试语法分析程序,了解语法分析器的组成结构以及对文法的要求,掌握基于LL(1)文法和算符优先文法的语法分析程序的实现方法。通过设计、编写和调试语法制导翻译程序,掌握从语句的语法出发,构造相应的语义子程序,实现自定义语言的语法制导翻译。

二、设计(实验)正文

  1. 词法分析器设计 
    1. 整体设计分为四个函数和主函数。
    2. ifzm(string s)函数判断当前字符是否为下划线或字母。 ifsz(string s)函数判断当前字符是否为数字。 ifsf(string s)函数判断当前字符是否为算符或界符。 ifsf2(string s)函数判断当前字符是否为双字符算符的第二位。
    3. 在主程序中先初始化。
  • 定义了char s,来暂时存储读入读出的当前字符。

第二,定义了3个vector类型的数组v1,v2,v5。v1负责存放程序拆解除去注释后的字符串,v2负责暂时存放连续读取的几个字符,来组成每个词法单位。V5负责存放标识符和数字具体的值,供v4识别。

第三,定义了两个数组int v3[100][2],v4[100][2],来存放词法表和符号表。其中符号表第二位不存储符号具体的值,而是存放符号在v5中的位置,读取时通过位置从v5中找到具体的符号。

第四,定义了5个整数int point1=0,point2=0,head1=1,head2=101,whichone=1。其中point1指向v3数组中要新增一行的位置。point2是指向v4数组要新增一行的位置。head1是符号表中下一标识符应在的位置,head2是符号表中下一数字应在的位置。 whichone是在读取到数字时根据其中是否有小数点定义值,供后续判断。

    1. 主程序的设计思路为:

第一,打开文件按字符读文件,每次读一个,在未读取到终结符前循环执行。每次读取一个字符,先判断此处是否为注释,若存在连续的两个‘/’‘/’符号表示此处往后一行都是注释,循环读完此行,不写入数组。其他情况将字符依次写入数组v1。

第二,从数组v1中依次读一个字符,当未读完时,循环执行。读出一个后首先判断是否为字母,如果是字母则接着连续判断接下来是否为字母或数字或下划线,当不是其中之一时停止。停止前读取的字符都进入v2存储,停止后,将v2转为字符串后清空。调用子函数判断该字符串是否为关键字,若是关键字则更新词法表,若不是关键字则是标识符,更新符号表v4和词法表v3和v5。然后循环到开头。

第三,如果从v1中读到的字符不是字母,但该字符是数字则接着判断接下来是否为连续的数字或小数点,判断到不是其中之一时停止,其中读到小数点时将whichone置2。停止前所有读到的字符都进入v2。将v2转为字符串然后清空。通过whichone判断该数字为整形还是实型,然后判断词法表中是否已存在,更新词法表v4,符号表v3和v5。然后循环到开头读字符。

第四,如果从v1中读取的字符不是字母也不是数字,但为算符或界符,则接着判断是否为双字符算符,将得到的算符或界符更新词法表v3。然后循环到开头读字符。

第五,如果从v1中读到的字符不是字母,不是数字,也不是算符或界符,则为无效字符,忽略,指针加一,直接循环到开头读字符。

第六,当v1中的字符操作完时,将词法表v3中的内容写入token.txt文件中,通过符号表v4第二列找到v5中对应的具体符号或数字,结合符号表v4写入symbol.txt文件。整个程序结束。

  1. 语法分析器设计
    1. 采用了递归下降的语法分析法,程序设计分为20个函数和主函数,每个函数对应一条语法。语法分7个语法单位。
    2. 在程序开始前先初始化。

第一,定义了一个node结构,有name和addr两个属性,分别存放词法表每行的单词名和地址。

  • 定义了一个vector类型的数组,用来存放从文件中读出的词法表。
  • 定义了int类型的变量point,用来指向当前在arr数组中读到的位置。
    1. 程序整体设计:采用递归下降分析法,对每条语法写一个函数,函数中的操作对应语法的结构,对于语法单位中包含另一个语法单位的情况采用函数递归调用的方法,在函数中调用下一个函数,来实现语法的分析。对于语法中固定关键字或算符界符的情况让point++表示已经接受了这个单词。
    2. 函数的设计,以Program来详细举例,剩下的函数原理相同

第一,对Program语法单位,有3条语法,对应程序中3个函数。void Program()方法实现<程序>对应的语法,开始先point加4,跳过main,(,),{四个字符,然后递归调用StateList()函数,表示递归分析了<语句列表>语法,接下来如果下一个字符是}则表示识别到完整Program语法单位,point加1然后写入文件Program语法单位,否则输出错误标志。同理,void State()函数对应<语句列表>这条语法,先递归调用SingleSta(),表示递归分析了<单语句>语法结构,接着判断下一字符如果不是}则表明程序未结束,递归调用自身。void SingleSta()函数对应<单语句>对应的语法,根据下一个读到的单词来判断调用哪个函数。其他函数同理实现递归分析。

    1. 主函数设计:先读文件,从文件中读出词法表,一次循环取出两个,对应一个单词的名称和地址,存入arr数组供后续分析。然后调用Program()函数,通过函数内部的递归调用来实现程序语法结构的分析。
  1. 语义分析器设计。
    1. 在语法分析器的基础上改进实现语义分析器,程序结构类似语法分析器,由18个函数和主函数组成。不同之处在于给程序中定义了属性,在程序中加入了填写语义分析表,并链,回填部分。
    2. 程序的总体设计:程序按照课本上三个词法分析表设计18个函数来编写每条语法对应的语义分析动作,然后通过递归调用来实现整个程序的翻译。设计结构MyE和MyS对应语义分析中的E和S,并设计内部属性来对应E的true和false属性,S的next属性来实现在递归调用的同时实现属性的自下向上传递。并在每个函数中根据获得的属性来实现并链和回填。
    3. 在程序开始前先初始化。

第一,定义了3个结构体:node,MyE,MyS。node结构同实验二。MyE结构对应课本表6-14中的E,有两个属性vector类型的True和False,对应E的两个属性E.true和E.false。MyS同理。属性设计为vector类型便于并链和回填时操作,可方便找出每个属性数组中包括哪些内容并方便的加入新的内容和读取已有的内容。

第二,定义了一个vector类型的数组arr,同实验二。定义了一个数组int arr1[1000][4],来存放语义分析中生成的四元式。

第三,定义了三个int类型的变量point=0,nowpoint=1,pointtemp=201。Point指向当前arr数组读到的位置。nowpoint相当于课本中的nextquad,来指向语义数组中下一条存放的位置。pointtemp指向下一个生成的临时变量序号,从201开始。

    1. 函数的设计。函数的结构和实验二语法分析器的设计类似,不同之处在于:

第一,将一些函数由void类型改为int或MyE或MyS类型。这样在递归调用函数时返回的就是int,MyE,MyS类型的变量,进而实现属性的传递。

第二,在函数中增加了并链和属性的传递,以<布尔项>函数举例,在语义分析时,需要设置E.true=merge(E1.true,E2.true),E.false=E2.false。通过循环将E1.True数组中的内容和E2.True数组中的内容加入E.True数组中,实现并链。通过循环将E2属性E2.False数组中的内容加入E.False数组中,实现属性的传递。其他函数同理实现并链和属性传递。

第三,在函数中加入了回填。以<布尔项>函数举例,在语义分析时,需要实现backpatch(E.false,M.quad),此时以循环的方式读出E.False数组中的每一个E.False[i],并将arr数组中对应的arr[E.False[i]][3]更改为Mq,实现回填。其他函数同理实现回填。

第四,在函数中加入了表达式的生成。以<关系式>函数举例,在语义分析时需要实现emit(‘j’relop.op’,’id1.place’,’id2.place’,’’0’),emit(‘j,_,_,0’)。通过函数返回值找到arg1,arg2,op,然后设置arr1[nowpoint][0]=op, arr1[nowpoint][1]=arg1, arr1[nowpoint][2]=arg2, arr1[nowpoint][3]=0来实现一条四元式的添加,第二条同理。其他函数同理生成四元式。

    1. 主函数的设计:先读文件,读出词法表存入arr数组备用,然后调用Program()函数,通过函数内部递归调用的方法实现程序的语义分析。

三、课程设计(综合实验)总结或结论

  1. 通过独立思考和查阅资料,我较为完整的完成了此次课程设计。这是一个综合性的程序编写,要用到多方面的知识。在课程设计中我学到了很多新的知识也遇到了一些问题。
    1. 在进行语法分析器实验时,我先考虑预测分析法,试图手动分析18条语法消除左递归并画出预测分析表,通过较大的工作量我完成了这种方法,但我发现这种方法写出来的程序不具有灵活性,因为语法已经手动分析出了写死的预测分析表,很难实现语法的增加或减少。经过考虑我放弃了这种方法转而采用递归下降分析法,为每条语法写一个程序,通过程序间递归调用实现语法分析,这样的程序具有可更改的灵活性。
    2. 在进行语义分析器实验时,刚开始不知道要怎么实现回填,经过思考决定尝试定义结构,并使函数返回值,通过函数返回具有属性值的变量来实现属性的自下向上传递,尝试后发现成功运行。

四、参考文献

附录(设计流程图、程序、表格、数据等)

你可能感兴趣的:(实验报告,课程设计,经验分享)