编译程序实验指导书讲解教学提纲
编译程序实验指导书讲解教学提纲
编译程序实验指导书解讲.编译程序实验指导书实验目的:用C语言对一个C语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。
1.词法分析1.1 实验目的设计、编制并测试一个词法分析程序,加深对词法分析原理的理解。
1.2 实验要求1.2.1 待分析的C语言子集的词法1. 关键字main if else int char for while所有的关键字都是小写。
2.专用符号= + - * / < <= > >= == != ; : , { } [ ] ( )3.其他标记ID和NUM通过以下正规式定义其他标记:→letter(letter|digit)*ID→digit digit*NUMletter→a|…|z|A|…|Zdigit→0|…|9…4.空格由空白、制表符和换行符组成空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。
1.2.2 各种单词符号对应的种别码表1 各种单词符号的种别码单词符号种别码单词符号种别码单词符号种别码main 1 = 21 , 32int 2 + 22 : 33char 3 - 23 ; 34if 4 * 24 > 35else 5 / 25 < 36for 6 ( 26 >= 37while 7 ) 27 <= 38ID 10 [ 28 == 39MUN 20 ] 29 != 40{ 30 ‘\0' 1000} 31 ERROR -11.2.3 词法分析程序的功能输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中,. syn为单词种别码。
. Token为存放的单词自身字符串。
. Sum为整型常量。
具体实现时,可以将单词的二元组用结构进行处理。
例如,对源程序main(){int i=10;while(i) i=i-1;}的源文件,经词法分析后输出如下序列:(1,main) (26,() (27,)) (30,{} (2,int) (10,i) (21,=) (20,10) (34,;) (7,while) (26,() (10,i) (27,)) (10,i) (21,=) (10,i) (23,-) (20,1) (34,;) (31,))1.3 词法分析程序的主要算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号。
《编译技术》课程实验指导书
《编译技术》课程实验指导书实验一词法分析一.实验目的1、学会针对DFA转换图实现相应的高级语言源程序。
2、深刻领会状态转换图的含义,逐步理解有限自动机。
3、掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。
二.实验内容TINY计算机语言的编译程序的词法分析部分实现。
从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。
为了简化程序的编写,有具体的要求如下:(1)数仅仅是整数。
(2)空白符仅仅是空格、回车符、制表符。
(3)代码是自由格式。
(4)注释应放在花括号之内,并且不允许嵌套TINY语言的单词三.实验要求要求实现编译器的以下功能:(1)按规则拼单词,并转换成二元式形式(2)删除注释行(3)删除空白符 (空格、回车符、制表符)(4)显示源程序,在每行的前面加上行号,并且打印出每行包含的记号的二元形式(5)发现并定位错误。
词法分析进行具体的要求:(1)记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。
(2)词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。
(3)标识符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标识符。
实验二递归下降语法分析器设计一、实验目的(1)加深对递归下降分析法一种自顶向下的语法分析方法的理解。
(2)根据文法的产生式规则消除左递归,提取公共左因子构造出相应的递归下降分析器。
二、实验内容根据课堂讲授的形式化算法,编制程序实现递归下降分析器,能对常见的语句进行分析。
编译技术--实验指导书
《编译技术》实验指导书湘潭大学信息工程学院计算机工程系何春梅2015-09-01实验课时说明《编译技术》课总课时为32/8学时,其中实验课时为8学时,课时分配为:前三个实验是必做实验:其中DFA的模拟程序2学时、DFA的化简2学时、LL(1)文法判断程序4学时。
后面3个实验为学生根据自己安排选做实验。
目录实验1 DFA模拟程序 1 实验2 DFA化简 2 实验3 LL(1)文法判断程序 4 实验4 基于预测分析表法的语法分析程序(1) 5 实验5 基于预测分析表法的语法分析程序(2) 6 实验6 中间代码生成:逆波兰式的产生与计算8实验1 词法程序设计——DFA模拟程序一、实验目的通过实验教学,加深学生对所学的关于编译的理论知识的理解,增强学生对所学知识的综合应用能力,并通过实践达到对所学的知识进行验证。
通过对DFA模拟程序实验,使学生掌握词法分析的实现技术,及具体实现方法。
通过本实验加深对词法分析程序的功能及实现方法的理解。
二、实验环境供Windows系统的PC机,可用C++/C#/Java等编程工具编写三、实验内容1、定义一个右线性正规文法,示例如(仅供参考)G[S]:S→aU|bV U→bV|aQV→aU|bQ Q→aQ|bQ|e实验前要考虑清楚用哪种数据结构存储上述文法。
2、构造其有穷确定自动机,如3、利用有穷确定自动机M=(K,Σ,f, S,Z)行为模拟程序算法,来对于任意给定的串,若属于该语言时,该过程经有限次计算后就会停止并回答“是”,若不属于,要么能停止并回答“不是”。
K:=S;c:=getchar;while c<>eof do{K:=f(K,c);c:=getchar; };if K is in Z then return (‘yes’)else return (‘no’)四、实验方式与要求1、每位同学定义的语言或文法不同,上机编程实现2、实验报告格式要求书写要点:概要设计(总体设计思想);详细设计(程序主流程、自动机的存储格式、关键函数的流程图);结果分析(输入与输出结果、存在问题及有待改进善的地方、实验心得)。
编译原理实验指导书
编译原理实验指导书计算机学院实验1 词法分析程序一、实验目的构造simple语言的词法分析程序,程序要求能对输入的字符串流进行词法分析。
在实验的过程中,学会应用单词分析的方法——NFA(非确定有穷自动机)和DFA(确定有穷自动机),加深对词法分析原理的理解。
二、实验内容编写为任一正则文法(见实验参考(一)simple惯用的词法)构造非确定有穷自动机NFA并转换成确定有穷自动机DFA,并对任给的一个输入串(见实验参考(二)测试用输入串)进行词法分析的程序,程序的输出为单词的序列(见实验参考(三)程序输出形式)。
三、实验参考(一)simple 惯用的词法1. 下面是语言的关键字:Begin if then while do end所有的关键字都是保留字,并且必须是小写。
2. 下面是专用符号::= + * / < <= <> > >= = ; ( ) #3. 其他单词是标识符(ID)和整型常数(NUM),通过下列正规式定义:ID = letter(letter| digit)*NUM = digit digit*letter = a |…| z | A |…| Zdigit = 0 |…| 9小写和大写字母是有区别的。
思考:构造实数的正规表达式,力争实现对实数的识别及表示。
4. 空格由空白、换行符和制表符组成。
空格一般用来分隔ID、NUM、运算符和关键字,词法分析阶段通常被忽略。
5. 各种单词符号对应的种别码如下表所示:(二)词法分析程序的功能1. 输入为所给文法的源程序字符串。
2. 程序的输出形式为单词串的输出形式。
所输出的每一单词,均按形如(syn,token和sum)的二元式编码。
其中,syn 为单词种别码;token为存放的单词自身字符串;sum为整型常数。
3.测试源程序片断:begin x:=9; if x>0 then x:=2*x+1/3;end #。
编译原理实验指导书讲解
编译原理实验指导书实验1 词法分析实验目的1.巩固对词法分析的基本功能和原理的认识。
2.能够应用自动机的知识进行词法分析。
3.理解并处理词法分析中的异常和错误。
实验要求一、对学生要求:1.掌握词法分析的基本功能,并将其实现。
2.词法分析程序应具有较好的可扩展性,应清晰明确。
3.除对相关问题的全面考虑外,还需对局部作一些优化考虑(如符号表)。
二、对实验指导教师要求:1.明确词法分析的基本功能和原理。
2.在词法分析中哪些地方体现自动机意识。
3.词法分析的异常和错误处理。
4.编写并运行该题目程序代码,具有该题目的参考答案。
5.深刻理解题目内涵,能够清晰描述问题,掌握该题目涉及的知识点,指导学生实验时需要注意的问题。
实验内容1.任务描述:给定一个高级语言源程序作为输入,运用词法分析的知识根据下面给出的词法规则对源程序分析,输出分析后所生成的token序列和符号表,token序列和符号表以文件的形式输出,注意输出格式具有可读性,该步骤的输出将会作为以后实验的输入,所以输出要便于计算机读取。
2.所用高级语言的文法产生式说明:下列是一个简化的C语言文法产生式列表,其中斜体为产生式中的变量,加粗的是终结符,终结符或者是C语言中的保留字,或者Program—> id( ){Slist}Slist—> Dlist Olist | Olist | εDlist—> Dlist D | DD—> type id ;Olist—> Olist O | OO—> id=expression;| if(expression) {Olist} else {Olist}| if (expression ) {Olist}| while (expression) {Olist}expression—> simple_expression| simple_expression relop simple_expressionsimple_expression—> term | simple_expression addop termterm—> factor | term mulop factorfactor—> id | num | ( expression) | !factortype—> int3.词法规则说明:letter代表一个大写或小写字母,区分大小写,digit代表一个数字。
《编译原理》实验指导书
《编译原理》实验指导书编著陈志刚中南大学信息科学与工程学院2006年11月第一部分词法分析(实验一必作)实验一词法分析程序设计与实现一、实验目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
二、实验内容自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。
词法分析程序的实现可以采用任何一种编程语言和编程工具。
从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验要求:1.对单词的构词规则有明确的定义;2.编写的分析程序能够正确识别源程序中的单词符号;3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;四、实验步骤1.定义目标语言的可用符号表和构词规则;2.依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束;3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;4.对不正确的单词,做出错误处理。
五、实验报告要求详细说明你的程序的设计思路和实现过程。
用有限自动机或者文法的形式对词法定义做出详细说明,说明词法分析程序的工作过程,说明错误处理的实现。
参考资料一、程序要求1、以下面一段程序为例main() {int a,b;a = 10;b = a + 20;}2、需要识别的词1.关键字:if、int、for、while、do、return、break、continue;单词种别码为1。
2.标识符;单词种别码为2。
3.常数为无符号整形数;单词种别码为3。
4.运算符包括:+、-、*、/、=、、<、=、<=、!= ;单词种别码为4。
编译方法实验指导书
(1) 实验一 源程序的输入和扫描 实验目的: 编制一个源程序的输入过程,从键盘、文件或文本框 输入若干行语句,依次存入输入缓冲区(字符型数据)。 实验要求:在进行本实验之前,应熟练课程内容,在上机之前做好 实验计划,编写好相应的代码 . 实验内容:编制一个扫描子程序,该子程序中每次调用能依次从存 放源程序的输入缓冲区中读出一个有效字符。 (2) 实验二 算符优先文法处理算术表达式与赋值语句 实验目的:算术表达式和赋值语句的文法是(学生可以根据需要适当 改变): S→i=E E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组 基本操作,每一基本操作用四元式表示。 实验要求:阅读课本有关章节,花一周时间确定算术表达式的文法, 设计出算符优先关系表;考虑好设计方案;设计出模块结构、测试数 据,初步编制好程序。 实验内容:编制能够根据文法及算符优先矩阵生成四元式序列的程序
{ str_test[p_test]=str[i]; i++; if(str[i-1]=='+') /*handle ++ and +=*/ { if(str[i]=='='||str[i]=='+') { str_test[++p_test]=str[i]; str_test[++p_test]='\0'; output(str_test,findsymble(str_test)); for(p_test=0;p_test<=M;p_test++) str_test[p_test]=0; p_test=0; i++; continue; } } if(str[i-1]=='-') /*handle – and -=*/ { if((str[i]=='='||str[i]=='-')||(str[i]=='>')) { str_test[++p_test]=str[i]; str_test[++p_test]='\0'; output(str_test,findsymble(str_test)); for(p_test=0;p_test<=M;p_test++) str_test[p_test]=0; p_test=0; i=i+1; continue; } } if(str[i-1]=='=') /*handle ==*/ { if(str[i]=='=') { str_test[++p_test]=str[i]; str_test[++p_test]='\0'; output(str_test,findsymble(str_test)); p_test=0;p_test<=M;p_test++) str_test[p_test]=0; p_test=0; i=i+1; continue; } } if(str[i-1]=='<'||str[i-1]=='>') /*handle <= or >= or << or >> or <>*/ { if(str[i]=='='||str[i]=='<'||str[i]=='>') { str_test[++p_test]=str[i]; str_test[++p_test]='\0'; output(str_test,findsymble(str_test)); for(p_test=0;p_test<=M;p_test++) str_test[p_test]=0; p_test=0; i=i+1; continue; } }
《编译原理》实验指导书(吴元斌)
《编译原理》实验指导书“编译原理”课程是计算机本科专业的必选课程,上机实验是该课程的重要环节,实验学时数为8学时。
一个编译程序把源程序翻译成等价的目标程序,一般应做词法分析、语法分析、语义分析、代码生成和代码优化等五个方面的工作,为了使学生对其有较深的理解,必须根据这五个方面设计实验。
本指导书正是根据课程的内容,将实验分为前期准备阶段、基本操作阶段和技术提高阶段三个阶段进行:①前期准备阶段的实验主要是为后续实验做好准备,应围绕编译原理课程进行设计,如:学生可根据教科书的内容,设计一个源程序的输入和扫描程序,并完成相应的设计报告;②基本操作阶段的实验是围绕着编译原理的五个方面的工作来进行,其内容主要是词法分析、语法分析、语义分析、代码生成和代码优化等,如:简单的词法分析程序、LL(1) 分析法算法、语义分析程序、中间代码和目标代码生成算法的实验,这些实验基本上包括了以上知识要点,学生可结合书本上有关的知识来完成;③技术提高阶段的实验是综合性课程设计实验,根据编译原理编制应用程序,不仅要求把书本上的内容掌握好,同时还需要自学一些相关的知识。
实验一、词法分析(2学时)一、实验目的熟悉正规文法、正规式和有穷自动机,了解词法分析的主要任务,掌握词法分析是如何根据正规文法规则逐一分析词法得到属性字的,即掌握了词法分析过程。
二、实验内容编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。
三、实验原理词法分析是编译过程的第一步,要想做好该实验,必须熟悉正规文法、正规式和有穷自动机的概念和原理,实验前须先定义语言的正规文法或正规式,构造确定的有穷自动机,然后根椐有穷自动机设计程序模块,源程序的输入。
1四、实验步骤(一)准备:1.阅读课本有关章节,花二天时间明确语言的语法,写出基本保留字、标识符、常数、运算符、分隔符和程序例。
编译原理实验指导书
编译原理实验指导书第1节概述1、本课程实践的目的和任务编译原理是一门实践性很强的课程,只有通过实践,才能真正掌握。
实际的编译程序是十分复杂的,有时由多达十几万条指令组成。
为此,编译原理的实践教学,采用简化编译过程的办法,选择最关键的3个环节──词法分析、语法分析(包括语义处理、产生无优化的目标指令)、连接调试,进行编程和调试训练。
每个环节作为一个实践课题。
2、实践方法任何一个实用的高级语言,其语法都比较复杂,如选其作为源语言,很难实践全过程。
故本实践将定义一个简化的语言──PASCAL语言的一个子集作为源语言,也可以自行定义一个简单的C语言子集,在3个题目中选择两个题目,也可以自行选择与编译技术相关的实验题目,设计调试出它的编译程序。
前后贯穿这一条主线进行实践。
每次都可利用课余时间编程,利用上机时间进行输入和调试。
建议使用C或C++或JAVA语言。
3、实践报告的规范和要求每个课题完成后写出实践报告。
实践报告包括程序设计时考虑的算法和方法;调试过程中出现的问题和解决的措施;提交电子版的程序清单和调试时所用的源程序。
4、简化的PASCAL语言子集的定义〈PASCAL子集程序〉→〈变量说明〉〈分程序〉。
〈变量说明〉→〈空〉|VAR〈变量表〉:INTEGER;〈变量表〉→〈变量〉|〈变量〉,〈变量表〉〈变量〉→〈标识符〉〈分程序〉→BEGIN〈语句组〉END〈语句组〉→〈语句〉|〈语句〉;〈语句组〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈WHILE语句〉|〈分程序〉〈赋值语句〉→〈变量〉:=〈算术表达式〉〈条件语句〉→IF〈布尔表达式〉THEN〈语句〉ELSE〈语句〉〈WHILE语句〉→WHILE〈布尔表达式〉DO〈语句〉〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉〈项〉→〈初等量〉|〈项〉*〈初等量〉|〈项〉/〈初等量〉〈初等量〉→〈无符号数〉|〈变量〉|(〈算术表达式〉)〈关系表达式〉→〈算术表达式〉〈关系运算符〉〈算术表达式〉〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉〈无符号数〉→〈数字〉|〈无符号数〉〈数字〉〈关系运算符〉→〈|〈=| =| 〉=| 〉|〈〉〈字母〉→ A│B│C│D│E│F│G│H│I│J│K│L│M│N│O│P│Q│R│S│T││U│V│W│X│Y│Z〈数字〉→ 1│2│3│4│5│6│7│8│9│0第2节词法分析本节进行词法分析程序的编程与调试。
《编译原理》实验教学大纲
《编译原理》实验教学大纲一、实验目的和任务编译原理是计算机科学与技术专业的一门重要课程,它主要研究的是将高级语言程序翻译成机器语言程序的方法和技术。
通过本实验课程的学习,旨在使学生掌握编译原理的基本原理和方法,培养学生对编译器结构与构造技术的专门知识和技能,为学生今后进行编译器设计与实现打下基础。
二、实验设备和工具1.计算机和相关硬件设备2. 编程语言的开发环境,如C/C++或Java三、实验内容1.实验一:词法分析器设计与实现a)实验目的:学习词法分析器的原理和设计方法,掌握正则表达式、DFA和NFA的转换方法。
b)实验任务:i.设计并实现一个词法分析器的原型,能够正确地识别出给定的程序中的词法单元。
ii. 使用给定的正则表达式设计并实现识别给定程序中的关键字、标识符、常量等的词法分析器。
2.实验二:语法分析器设计与实现a)实验目的:学习语法分析器的原理和设计方法,掌握上下文无关文法和LR分析表的构造方法。
b)实验任务:i.学习并理解上下文无关文法和LR分析表的构造方法。
ii. 设计并实现一个简单的递归下降语法分析器。
3.实验三:语义分析器设计与实现a)实验目的:学习语义分析器的原理和设计方法,掌握语义动作的定义和处理方法。
b)实验任务:i.学习并理解语义分析器的原理和设计方法。
ii. 设计并实现一个简单的语义分析器,能够对给定的程序进行语义分析和语义动作的处理。
4.实验四:中间代码生成器设计与实现a)实验目的:学习中间代码生成器的原理和设计方法,掌握中间代码的生成和优化方法。
b)实验任务:i.学习并理解中间代码生成器的原理和设计方法。
ii. 设计并实现一个简单的中间代码生成器,能够将给定的程序翻译成中间代码。
5.实验五:目标代码生成器设计与实现a)实验目的:学习目标代码生成器的原理和设计方法,掌握目标代码的生成和优化方法。
b)实验任务:i.学习并理解目标代码生成器的原理和设计方法。
ii. 设计并实现一个简单的目标代码生成器,能够将中间代码翻译成目标代码。
编译实验指导书-2012.9.18
编译原理实验指导书实验一词法分析一、实验目的通过实现PL/0语言(一种示例小语言)的词法分析器,理解词法分析过程,掌握程序各部分之间的接口安排。
二、实验要求1、要求每位同学单独完成词法分析器,并接受检查;2、撰写实验报告。
(1) 用有限自动机画出“三、实验内容”中的词法规则;(2) 实验报告不要摘抄全部代码,但需要流程图的形式描述程序结构;(3) 必须书写设计和实现的过程中出现的一些问题以及解决方法。
三、实验内容1、PL/0语言的单词结构关键字(10个):begin, end ,if ,then, while, do, const, var,call,procedure标识符:字母序列,最大长度10常数:整型常数算符和界符(17个):+,-,*,/,odd,=,<>,<,>,<=,>=,:=,(,) ,, ,.,;2、单词的种别SYM_IDENTIFIER, 标识符SYM_NUMBER, 常数SYM_PLUS, +SYM_MINUS, -SYM_TIMES, *SYM_SLASH, /SYM_ODD, oddSYM_EQU, =SYM_NEQ, <>SYM_LES, <SYM_LEQ, <=SYM_GTR, >SYM_GEQ, >=SYM_LPAREN, (SYM_RPAREN, )SYM_COMMA, ,SYM_SEMICOLON, ;SYM_PERIOD, .SYM_BECOMES, :=SYM_BEGIN, beginSYM_END, endSYM_IF, ifSYM_THEN, thenSYM_WHILE, whileSYM_DO, doSYM_CONST, constSYM_V AR, varSYM_CALL,callSYM_PROCEDURE procedure3、PL/0的语言的词法分析器将要完成以下工作:(1)跳过分隔符(如空格,回车,制表符);(2)识别诸如begin,end,if,while等保留字;(3)识别非保留字的一般标识符,此标识符值(字符序列)赋给全局量id,而全局量sym赋值为SYM_IDENTIFIER。
编译技术课程设计大纲及指导书
《编译技术》课程设计大纲及指导书实验名称:根据给定的文法完成一个小型编译器。
实验目的:本课程设计实验项目的目标是通过实际构造一个完整的编译器,加深对编译器实现原理的理解,了解完整编译系统的构造方法。
实验类型:验证型、提高型实验学时:50学时实验描述:根据各难度的题目的说明,选择一个难度等级,将获得一份随机分配的该难度等级的文法。
根据获取的文法实现编译器:1.难度等级:低目标:完成编译器及解释执行程序,解释执行程序对编译器产生的PCODE能解释执行,产生运行结果文法:PL/0文法(与教材上的文法略有差别)优化:无中间代码:无目标码:PCODE最高分:652.难度等级:中目标:完成编译器及解释执行程序,解释执行程序对编译器产生的PCODE能解释执行,产生运行结果文法:扩充C0文法优化:无中间代码:无目标码:PCODE最高分:853.难度等级:高目标:实现编译器,生成X86汇编或MIPS汇编文法:扩充C0文法(无实型)优化:基本块内部的公共子表达式删除(DAG图);全局寄存器分配(引用计数或着色算法);数据流分析(通过活跃变量分析,或利用定义-使用链建网等方法建立冲突图);其它优化自选;代码生成时合理利用临时寄存器(临时寄存器池),并能生成较高质量的目标代码;中间代码:四元式目标码:32位X86汇编或MIPS汇编(任选一)最高分:100实验要求:1. 每人独立完成一份作业2. 采用递归子程序法进行语法分析,所有代码要求手工编程实现3. 可以有图形用户界面4. 完成一份文档,包括以下内容:1) 需求说明:包括文法及其分析说明、目标代码说明、优化方案说明(高)2) 详细设计:包括程序结构、类、方法/函数的功能描述和调用依赖关系、关键算法、符号表管理方案、存储分配方案、解释执行程序结构(低中)、解释执行过程(低中)、四元式设计(高)、优化算法设计(高)、出错处理方案3) 操作说明:包括程序安装、环境配置;程序启动后,编译、运行、结果显示等操作的说明4) 测试报告:包括至少10个测试程序的源程序及测试结果(无需截屏)(其中5个是有错误的文件,如有扩充,还需另外提供5个测试程序,扩充后的语言必须包含原来的语言)、测试结果分析5) 总结感想:完成本实验项目后的感想及建议5. 用C/C++语言实现6. 开发环境Visual Studio或CodeBlocks7. 提交完整的项目/工程文件,在集成开发环境下可编译运行8. 目录命名及组织阶段成果以”学号_姓名_任务说明”命名提交的文档;最终成果组织为如下三个文件夹:源代码文档测试程序提交时打包为一个zip文件,按如下规则命名:学号_姓名[_MIPS][_申优].zip(如12061001_×××_申优.zip ,12061001_×××.zip,12061001_×××_MIPS_申优.zip)考核:1. 检查文档内容是否齐全、正确。
《编译原理》科学实验指导说明书
《编译原理》实验指导书实验一词法分析器的设计一、实验目的和要求加深对状态转换图的实现及词法分析器的理解。
熟悉词法分析器的主要算法及实现过程。
要求学生掌握词法分析器的设计过程,并实现词法分析。
二、实验基本内容给出一个简单语言的词法规则,画出状态转换图,并依据状态转换图编制出词法分析程序,能从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单Error”,然后跳过错误部分继续显示)词法规则如下:三、实验时间:上机三次。
第一次按照自己的思路设计一个程序。
第二、三次在理论课学习后修改程序,使得程序结构更加合理。
四、实验过程和指导:(一)准备:1.阅读课本有关章节(c/c++,数据结构),花一周时间明确语言的语法,写出基本算法以及采用的数据结构和要测试的程序例。
2.初步编制好程序。
3.准备好多组测试数据。
(二)上课上机:将源代码拷贝到机上调试,发现错误,再修改完善。
(三)程序要求:程序输入/输出示例:输入如下一段:main(){/*一个简单的c++程序*/int a,b; //定义变量a = 10;b = a + 20;}要求输出如右图。
要求:(1) 剔除注解符(2) 常数为无符号整数(可增加实型数,字符型数等)(四)练习该实验的目的和思路:程序开始变得复杂起来,可能是大家以前编过的程序中最复杂的,但相对于以后的程序来说还是简单的。
因此要认真把握这个过渡期的练习。
程序规模大概为200行及以上。
通过练习,掌握对字符进行灵活处理的方法。
(五)为了能设计好程序,注意以下事情:1.模块设计:将程序分成合理的多个模块(函数/类),每个模块(类)做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
3.编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
4.程序设计语言不限,建议使用面向对象技术及可视化编程语言,如C++,VC,JA V A,VJ++等。
汇编语言程序设计实验指导书、实验教学大纲
附件1-3《汇编语言程序设计课程》实验教学指导书课程编号:撰写人:刘伏贵审核人:湘潭大学信息工程学院二○○七年十月十八日前言一、实验总体目标《汇编语言程序设计》是一门重要的专业选修课,同时也是一门实践性很强的课程。
通过实验使学生对所学的汇编语言程序设计内容加深理解,增强实践动手能力,培养学生分析问题和解决问题的能力,以及进行汇编语言程序设计的实践。
在汇编语言程序设计课程的学习过程中,将分别开出《汇编程序与调试器的使用》、《DOS 命令与磁盘文件操作》、《汇编语言与结构化程序设计》、《汇编语言子程序设计》、《十进制数据直接处理程序设计》、《结构数据与汇编语言程序设计》、《记录数据与汇编语言程序设计》、《汇编语言程序设计综合实验》等八个实验。
由于汇编语言程序设计涉及到硬件、操作系统等诸方面的知识,完成实验的难度大。
因此,要求每一个学生必须按照教师的安排和要求,认真完成每一个实验,从而达到培养现代程序设计基本素养的目的。
二、适用专业年级专业:计算机科学与技术、网络工程年级:二年级三、先修课程《C语言程序设计》、《计算机组成原理》四、实验项目及课时分配五、实验环境个人计算机:120台Win 32 操作系统MS DOSMASM 6.0 及其以上版本的汇编程序及配套的80x86 汇编语言程序开发环境六、实验总体要求1、汇编语言程序设计的实验课主要是供学生测试、调试汇编语言程序。
2、必须充分重视实验课。
实验课是汇编语言程序设计课程的重要组成部分,是理论联系实践的重要环节。
通过它,能够培养学生独立分析和解决问题的能力。
3、在每个实验之前,学生必须准备好被测程序的有关设计资料(包括程序的基本设计说明、程序流程图、汇编语言程序清单等)、测试数据、测试驱动程序、测试需要的“桩模块”等。
4、必须做好实验前的一切准备工作,包括程序测试/调试的详细过程安排等。
在实验中应严格按照预先确定的实验过程进行实验,决不允许在实验过程中准备实验程序、测试数据与测试/调试过程计划。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译程序实验指导书讲解编译程序实验指导书实验目的:用C语言对一个C语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。
1.词法分析1.1 实验目的设计、编制并测试一个词法分析程序,加深对词法分析原理的理解。
1.2 实验要求1.2.1 待分析的C语言子集的词法1. 关键字main if else int char for while所有的关键字都是小写。
2.专用符号= + - * / < <= > >= == != ; : , { } [ ] ( ) 3.其他标记ID和NUM通过以下正规式定义其他标记:ID→letter(letter|digit)*NUM→digit digit*letter→a|…|z|A|…|Zdigit→0|…|9…4.空格由空白、制表符和换行符组成空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。
1.2.2 各种单词符号对应的种别码表1 各种单词符号的种别码单词符号种别码单词符号种别码单词符号种别码main 1 = 21 , 32int 2 + 22 : 33char 3 - 23 ; 34if 4 * 24 > 35else 5 / 25 < 36for 6 ( 26 >= 37while 7 ) 27 <= 38ID 10 [ 28 == 39MUN 20 ] 29 != 40 { 30 ‘\0’ 1000} 31 ERROR -11.2.3 词法分析程序的功能输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中,. syn为单词种别码。
. Token为存放的单词自身字符串。
. Sum为整型常量。
具体实现时,可以将单词的二元组用结构进行处理。
例如,对源程序main(){int i=10;while(i) i=i-1;}的源文件,经词法分析后输出如下序列:(1,main) (26,() (27,)) (30,{} (2,int) (10,i) (21,=) (20,10) (34,;) (7,while) (26,() (10,i) (27,)) (10,i) (21,=) (10,i) (23,-) (20,1) (34,;) (31,))1.3 词法分析程序的主要算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号。
1. 主程序示意图主程序示意图如图1所示。
图1 词法分析主程序示意图其中初值包括如下两方面:(1)关键字表初值关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:char *KEY_WORDS[8]={“main”,”int”,”char”,”if”,”else”,”for”,”while”};为分析方便,这里把main作关键字处理。
(2) 程序中需要用到的主要变量:syn,token和sum。
2. 扫描子程序的算法思想首先设置三个变量:token用来存放构成单词符号的字符串;sum用来存放整型单词;syn 用来存放单词符号的种别编码。
扫描子程序主要部分流程如图2所示。
图2 词法分析程序流程2.语法分析2.1 实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析。
2.2 实验要求利用C语言编制递归下降分析程序,并对C语言的简单子集进行分析。
2.2.1 待分析的C语言子集的语法用扩充的BNF表示如下:(1) <程序>∷=main( )<语句块>(2) <语句块>∷=’{’<语句串>’}’(3) <语句串>∷=<语句>{;<语句>};(4) <语句>∷=<赋值语句>|<条件语句>|<循环语句>(5) <赋值语句>∷=ID=<表达式>(6) <条件语句>∷=if(<条件>)<语句块>(7) <循环语句>∷=while<条件><语句块>(8) <条件>∷=<表达式><关系运算符><表达式>(9) <表达式>∷=<项>{+<项>|-<项>}(10)<项>∷=<因子>{*<因子>|/<因子>}(11)<因子>∷=ID|NUM|(<表达式>)(12)<关系运算符>∷=<|<=|>|>=|==|!=2.3 语法分析程序的算法思想(1)主程序示意图如图3所示。
图3 语法分析主程序示意图(2)递归下降分析程序示意图如图4所示。
图4递归下降分析程序示意图(3)语句块分析过程示意图如图5所示。
图5语句块分析示意图(4)图6语句串分析示意图(5)statement (语句) 函数流程如图7所示;(6)expression(表达式)分析过程如图8所示;(7)term(项)分析过程如图9所示;(8)condition(条件)分析过程如图10所示;(9) factor (因子)分析过程如图11所示。
图7 statement 函数流程图8 expression 分析过程示意图 图9 term 分析过程示意图是 图10 condition 分析过程示意图11 factor分析过程示意图3.语义分析产生中间代码3.1 实验目的通过上机实验,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
3.2 实验要求采用递归下降语法制导翻译法对算术表达式、赋值语句、条件语句、循环语句进行语义分析生成四元式序列。
3.2.1 实验的输入和输出输入是语法分析提供的正确的单词串,输出是四元式序列。
例如,对于语句串i=2*3+4;if (i>10) j=3;while j>10 k=1;输出的四元式序列如下:(1)(*,2,3,T1)(2)(+,2,T1,T2)(3)(=,T2, ,i)(4)(j>,i,10,6)(5)(j<, , ,7))(6)(=,3, ,j)(7)(j<,j,10,9)(8)(j, , ,11)(9)(=,1, ,k)(10)(j, , ,7)(11) ......3.2.2算法思想1.设置语义过程(1). int gen(op,arg1,arg2,result)该函数是将四元式(op,arg1,arg2,result)送到四元式表中。
(2). char *newtemp( )该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,....(3). int merg(p1,p2)该函数将以p1和p2为头指针的两条链合并为一,合并后的链首为返回值。
(4). int bp(p,t)该函数的功能是把p所链接的每个四元式的第四区段都填为t。
2.主程序示意图图12 语义分析主程序示意图3.函数lrparser在原来语法分析的基础上插入相应的语义动作将输入串翻译成四元式序列。
在实验中我们只对表达式、if语句和while语句进行翻译,其具体翻译程序见实验实例。
4.实验实例/****************************************************//*文件:globals.h *//*定义分析器需要的一些数据结构、宏等 *//*本头文件必须在其他文件前引用 *//***************************************************/# ifndef _GLOBALS_H# define _GLOBALS_H# include <stdio.h># include <stdlib.h># include <string.h>/*单词种别码*/# define _SYN_MAIN 1# define _SYN_INT 2# define _SYN_CHAR 3# define _SYN_IF 4# define _SYN_ELSE 5# define _SYN_FOR 6# define _SYN_WHILE 7/*以上为关键字的单词种别码*/# define _SYN_ID 10 /*标识符的单词种别码*/ # define _SYN_NUM 20 /*整数的单词种别码*/# define _SYN_ASSIGN 21 /* = */# define _SYN_PLUS 22 /* + */# define _SYN_MINUS 23 /* - */# define _SYN_TIMES 24 /* * */# define _SYN_DIVIDE 25 /* / */# define _SYN_LPAREN 26 /* ( */# define _SYN_RPAREN 27 /* ) */# define _SYN_LEFTBRACKET1 28 /* [ */# define _SYN_RIGHTBRACKET1 29 /* ] */# define _SYN_LEFTBRACKET2 30 /* { */# define _SYN_RIGHTBRACKET2 31 /* } */# define _SYN_COMMA 32 /* , */# define _SYN_COLON 33 /* : */# define _SYN_SEMICOLON 34 /* ; */# define _SYN_LG 35 /* > */# define _SYN_LT 36 /* < */# define _SYN_ME 37 /* >= */# define _SYN_LE 38 /* <= */# define _SYN_EQ 39 /* == */# define _SYN_NE 40 /* != */# define _SYN_END 1000 /* 源程序结束标志 */# define _SYN_ERROR -1 /* error */# define MAXLENGTH 255 /* 一行允许的字符个数 */union WORDCONTENT { /*存放单词内容的联合*/ char T1[MAXLENGTH];int T2;char T3;};typedef struct WORD { /*单词二元组*/int syn;union WORDCONTENT value;} WORD;# endif/**************************************************//*文件:scan.h *//*定义词法分析器的接口 *//**************************************************/# ifndef _SCAN_H# define _SCAN_H/* 一个TAB占用的空格数 */# define _TAB_LENGTH 4/* 关键字结束标记*/# define _KEY_WORD_END "waiting for your expanding"/* 函数 Scaner 得到源程序里的下一个单词符号*/void Scaner(void);# endif/**************************************************//*文件:scan.c *//*分析器的词法扫描部分 *//**************************************************/# include "globals.h"# Include "scan.h"void Do_Tag(char *strSource); /* 识别标识符的中间状态 */ void Do_Digit(char *strSource); /* 识别数字的中间状态 */void Do_EndOfTag(char *strSource); /* 识别标识符最后的一个状态 */ void Do_EndOfDigit(char *strSource); /* 识别数字最后的一个状态 */ void Do_EndOfEqual(char *strSource); /* =,== */void Do_EndOfPlus(char *strSource); /* + */void Do_EndOfSubtraction(char *strSource); /* - */void Do_EndOfMultiply(char *strSource); /* * */void Do_EndOfDivide(char *strSource); /* / */void Do_EndOfLParen(char *strSource); /* ( */void Do_EndOfRParen(char *strSource); /* ) */void Do_EndOfLeftBracket1(char *strSource); /* [ */void Do_EndOfRightBracket1(char *strSource); /* ] */void Do_EndOfLeftBracket2(char *strSource); /* { */void Do_EndOfRightBracket2(char *strSource); /* } */void Do_EndOfColon(char *strSource); /* : */void Do_EndOfComma(char *strSource); /* , */void Do_EndOfSemicolon(char *strSource); /* ; */void Do_EndOfMore(char *strSource); /* >,>= */void Do_EndOfLess(char *strSource); /* <,<= */void Do_EndOfEnd(char *strSource); /* 用' \0 ' 作为源程序结束 */ void PrintError(int nColumn,int nRow,char chInput); /* 词法分析错误输出 */ void Scaner(void);/* 词法扫描函数 */extern char *strSource; /* 待分析的源程序 */extern FILE *fw ;/* 结果输出文件 */int gnColumn,gnRow, /* 行列号 */gnLocate, /* 下一个字符脚标 */gnLocateStart; /* 下一个单词开始位置 */Word uWord; /* 扫描出的单词 *//* 关键字表 */char*KEY_WORDS[20]={"main","int","char","if","else","for","while","void",_KEY_WORD_END};int IsDigit(char chInput) /* 判断扫描的字符是否数字 */{if (chInput<='9' && chInput>='0') return 1;else return 0;}int IsChar(char chInput) /* 判断扫描的字符是否字母 */{if ((chInput<='z' && chInput>='a')|| (chInput<='Z' && chInput>='A'))return 1;else return 0;}void Do_Start(char *strSource) /* 开始识别最先一个单词 */{gnLocateStart=gnLocate;switch (strSource[gnLocate]) { /* 根据第一个字符判断 */case '+': Do_EndOfPlus(strSource); break;case '-': Do_EndOfSubtraction(strSource); break;case '*': Do_EndOfMultiply(strSource); break;case '/': Do_EndOfDivide(strSource); break;case '(': Do_EndOfLParen(strSource); break;case ')': Do_EndOfRParen(strSource); break;case '[': Do_EndOfLeftBracket1(strSource); break;case ']': Do_EndOfRightBracket1(strSource); break;case '{': Do_EndOfLeftBracket2(strSource); break;case '}': Do_EndOfRightBracket2(strSource); break;case ':': Do_EndOfColon(strSource); break;case ',': Do_EndOfComma(strSource); break;case ';': Do_EndOfSemicolon(strSource); break;case '>': Do_EndOfMore(strSource); break;case '<': Do_EndOfLess(strSource); break;case '=': Do_EndOfEqual(strSource); break;case '\0': Do_EndOfEnd(strSource); break;default:if (IsChar(strSource[gnLocate])) { /* 是标识符或关键字 */Do_Tag(strSource);}else if (IsDigit(strSource[gnLocate])) { /* 可能是整数 */uWord.value.T2=strSource[gnLocate]-'0';Do_Digit(strSource);}else { /* 其他符号 */if (strSource[gnLocate]!=' ' && strSource[gnLocate]!='\t'&& strSource[gnLocate]!=' \n' && strSource[gnLocate]!='\r'] { PrintError(gnColumn,gnRow,strSource[gnLocate]);}if (strSource[gnLocate]=='\n ' || strSource[gnLocate}=='\r') { gnColumn++;gnRow=1;}else if (strSource[gnLocate]=='\t') {gnColumn+=_TAB_LENGTH;}else gnRow++;gnLocate++;Do_Start(strSouce);}break;}return;}void Do_Tag(char *strSource) /* 识别标识符的中间状态 */ {gnLocate++;gnRow++;if (IsChar(strSource[gnLocate]) || IsDigit(strSource[gnLocate])) {/* 是数字或者字母 */Do_Tag(strSource);}else Do_EndOfTag(strSource);return;}void Do_Digit(char *strSource) /* 识别整数的中间状态 */{gnLocate++;gnRow++;if (IsDigit(strSource[gnLocate])) { /* 是数字 */uWord.value.T2=uWord.value.T2*10+strSource[gnLocate]-'0'; /* 累加识别的数字 */ Do_Digit(strSource);}else Do_EndOfDigit(strSource);return;}void Do_EndOfTag(char *strSource) /* 标识符的最后状态 */{int nLoop;uWord.syn=_SYN_ID; /* 单词种别码缺省为标识符 */ /* 记录标识符 */strncpy(uWord.value.T1,strSource+gnLocateStart,gnLocate-gnLocateStart); uWord.value.T1[gnLocate-gnLocateStart]='\0';nLoop=0;while (strcmp(KEY_WORDS[nLoop],_KEY_WORD_END)) {/* 查关键字表,是否关键字 */if (! strcmp(KEY_WORDS[nLoop],uWord.value.T1)) {/* 比较和某关键字相符 */uWord.syn=nLoop+1; /* 设置正确的syn */break;}nLoop++;}return;}void Do_EndOfDigit(char *strSource) /* 识别数字的最后状态 */ {uWord.syn=_SYN_NUM;return;}void Do_EndOfEqual(char *strSource) /* =,== */{if (strSource[gnLocate+1]!='=') { /* = */uWord.syn=_SYN_ASSIGN;uWord.value.T3=strSource[gnLocate];}else { /* == */gnLocate++;gnRow++;uWord.syn=_SYN_EQ;strcpy(uWord.value.T1,"==");}gnLocate++;gnRow++;return;}void Do_EndOfPlus(char *strSource) /* + */ {uWord.syn=_SYN_PLUS;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfSubtraction(char *strSource) /* - */ {uWord.syn=_SYN_MINUS;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfMultply(char *strSource) /* * */ {uWord.syn=_SYN_ TIMES;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfDivide(char *strSource) /* / */ {uWord.syn=_SYN_DIVIDE;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfLParen(char *strSource) /* ( */ {uWord.syn=_SYN_LPAREN;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfRParen(char *strSource) /* ( */ {uWord.syn=_SYN_RPAREN;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfLeftBracket1(char *strSource) /* [ */ {uWord.syn=_SYN_LEFTBRACKET1;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfRightBracket1(char *strSource) /* ] */ {uWord.syn=_SYN_RIGHTBRACKET1;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfLeftBracket2(char *strSource) /* { */ {uWord.syn=_SYN_LEFTBRACKET2;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfRightBracket2(char *strSource) /* } */ {uWord.syn=_SYN_RIGHTBRACKET2;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfColon(char *strSource) /* : */ {uWord.syn=_SYN_COLON;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfComma(char *strSource) /* , */ {uWord.syn=_SYN_COMMA;uWord.value.T3=strSource[gnLocate];gnLocate++;return;}void Do_EndOfSemicolon(char *strSource) /* ; */ {uWord.syn=_SYN_SEMICOLON;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void Do_EndOfMore(char *strSource) /* >,>= */ {if (strSource[gnLocate+1]!='=') { /* > */uWord.syn=_SYN_LG;uWord.value.T3=strSource[gnLocate];}else { /*>= */gnLocate++;gnRow++;uWord.syn=_SYN_ME;strcpy(uWord.value.T1,">=");}gnLocate++;gnRow++;return;}void Do_EndOfLess(char *strSource) /* <,<= */ {if (strSource[gnLocate+1]!='=') { /* < */uWord.syn=_SYN_LT;uWord.value.T3=strSource[gnLocate];}else { /*<= */gnLocate++;gnRow++;uWord.syn=_SYN_LE;strcpy(uWord.value.T1,"<=");}gnLocate++;return;}void Do_EndOfEnd(char *strSource) /* 读到'\0',源程序结束 */{uWord.syn=_SYN_END;uWord.value.T3=strSource[gnLocate];gnLocate++;gnRow++;return;}void PrintWord(Word uWord) /* 打印二元组 */{if (uWord.syn<=_SYN_ID /* 关键字、标识符或者有错误 */|| uWord.syn==_SYN_ME /* >= */|| uWord.syn==_SYN_LE /* <= */|| uWord.syn==_SYN_EQ) { /* == */fprintf(fw,"\n(%d,\t%s)",uWord.syn,uWord.value.T1);}else if (uWord.syn==_SYN_NUM) { /* 数字 */fprintf(fw,"\n(%d,\t%d)",uWord.syn,uWord.value.T2);}else { /* 其他符号 */fprintf(fw,"\n(%d,\t%c)",uWord.syn,uWord.value.T3);}return;}void ApartWord(char *strSource) /* 根据输入的源程序识别所有的单词 */ {gnColumn=gnRow=1;gnLocate=gnLocateStart=0;while (strSource[gnLocate]) {Scaner( );}return;}void Scaner(void) /* 词法扫描函数 */{Do_Start(strSource); /* 识别出一个单词 */printWord(uWord); /* 打印二元组 */return;}void PrintError(int nColumn,int nRow,char chInput) /* 打印词法扫描发现的错误 */ {fprintf(fw,"\n 无法识别的单词--->Col:%d\tRow:%d\tChar:%c",nColumn,nRow,chInput); return;}/**************************************************//*文件:semanteme.h *//*定义语法(语义)分析器的接口 *//**************************************************/# ifndef _SEMANTEME_H# define _SEMANTEME_H/* 四元组的结构 */typedef struct QUAD {char op[MAXLENGTH]; /* 操作符 */char argv1[MAXLENGTH]; /* 第一个操作数 */char argv2[MAXLENGTH]; /* 第二个操作数 */char result[MAXLENGTH]; /* 运算结果 */}QUATERNION;void lrparse(void); /* 语法语义分析主函数 */# endif/**************************************************//*文件:semanteme.c *//*分析器的语法语义扫描部分 *//**************************************************/# include "globals.h"# include "scan.h"# include "semanteme.h"QUATERNION *pQuad; /* 存放四元组的元组 */int nSuffix,nNXQ, /* 临时变量的编号 */ntc,nfc;extern Word uWord; /* 扫描得到的单词 */extern int gnColumn,gnRow; /* 行列号 */FILE *fw; /* 打印结果的文件指针 */char *strFileName; /* 打印结果的文件名 */char *strSource; /* 源程序 */char *Expression(void);char *Term(void);char *Factor(void);void Statement_Block(int *nChain);void LocateError(int nColumn,int nRow) /* 定位语法错误 */{fprintf(fw,"\nCol:%d\tRow:%d--->",nColumn+1,nRow);}void error(char *strError) /* 输出扫描发现的错误 */{LocateError(gnColumn,gnRow);fprintf(fw,"%s",strError);return;}void Match(int syn,char *strError) /* 判断当前识别出的单词是否需要的单词,如果不是则报错,否则扫描下一个单词 */{if (syn==uWod.syn) Scaner( );else error(strError);return;}void gen(char *op,char *argv1,char *argv2,char *result) /* 生成一个四元式 */{sprintf(pQuad[nNXQ].op,op);sprintf(pQuad[nNXQ].argv1,argv1);sprintf(pQuad[nNXQ].argv2,argv2);sprintf(pQuad[nNXQ].result,result);nNXQ++;return;}void PrintQuaternion(void) /* 打印一个四元式 */{int nLoop;for (nLoop=1;nLoop<nNXQ;nLoop++) {fprintf(fw,"\n%d:%s,\t%s,\t%s",nLoop,pQuad[nLoop].op,pQuad[nLoop].argv1,pQuad[nLoop].argv2,pQuad[nLoop].result);}}char *Newtemp(void) /* 产生一个临时变量 */{char *strTempID=(char *) malloc(MAXLENGTH);sprintf(strTempID,"T%d",++nSuffix);return strTempID;}int merg(int p1,int p2) /* 合并p1和p2 */{int p,nResult;if (p2==0) nResult=p1;else {nResult=p=p2;while (atoi(pQuad[p].result)) {p=atoi(pQuad[p].result);sprintf(pQuad[p].result,"%d",p1);}}return nResult;}void bp(int p,int t) /* 将t回填到以p为首的四元式链中 */{int w,q=p;while (q) {w=atoi(pQuad[q].result);sprintf(pQuad[q].result,"%d",t);q=w;}return;}char *Expression(void){char opp[MAXLENGTH],*eplace,eplace1[MAXLENGTH],eplace2[MAXLENGTH]; eplace=(char *) malloc(MAXLENGTH);strcpy(eplace1,Term( ));strcpy(eplace,eplace1);while (uWord.syn==_SYN_PLUS || uWord.syn==_SYN_MINUS) { /* + - */sprintf(opp,"%c",uWord.value.T3);Scaner( );strcpy(eplace2,Term( ));strcpy(eplace,Newtemp( ));gen(opp,eplace1,eplace2,eplace);strcpy(eplace1,eplace);}return;}char *Term(void){char opp[2],*eplace1,*eplace2,*eplace;eplace=eplace1=Factor( );while (uWord.syn==_SYN_TIMES || uWord.syn==_SYN_DIVIDE) { /* * / */ sprintf(opp,"%c",uWord.value.T3);Scaner( );eplace2=Factor( );eplace=Newtemp( );gen(opp,eplace1,eplace2,eplace);eplace1=eplace;}return eplace;}char *Factor(void){char *eplace=(char *) malloc(MAXLENGTH);if (uWord.syn==_SYN_ID || uWord.syn==_SYN_NUM) { /* i */if (uWord.syn==_SYN_ID) sprintf(eplace,"%s",uWord.value.T1);else sprintf(eplace,"%d",uWord.value.T2);Scaner( );}else {Match(_SYN_LPAREN,"(");eplace=Expression( );Match(_SYN_RPAREN,")");}return eplace;}void Condition(int *etc,int *efc){char opp[3],*eplace1,*eplace2;char strTemp[4 ];eplace1=Expression( );if (uWord.syn<=_SYN_NE && uWord.syn>=_SYN_LG) { swich (uWord.syn) {case _SYN_LT:case _SYN_LG:sprintf(opp,"%c",uWord.value.T3);break;default:sprintf(opp,"%s",uWord.value.T1);break;}Scaner( );eplace2=Expression( );*etc=nNXQ;*efc=nNXQ+1;sprintf(strTemp,"j%s",opp);gen(strTemp,eplace1,eplace2,"0");gen("j","","","0");}else error("关系运算符");}void Statement(int *nChain) /* 语句分析函数 */{char strTemp[MAXLENGTH],eplace[MAXLENGTH];int nChainTemp,nWQUAD;switch (uWord.syn) {case _SYN_ID:strcpy(strTemp,uWord.value.T1);Scaner( );Mat ch(_SYN_ASSIGN,”=”);Strcpy(eplace,Expression( ));Match(_SYN_SEMICOLON,";");gen("=",eplace,"",strTemp);*nChain=0;break;case _SYN_IF:Match(_SYN_IF,"if");Match(_SYN_LPAREN,"(");Condition(&ntc,&nfc);bp(ntc,nNXQ);Match(_SYN_RPAREN,")");Statement_Block(&nChainTemp);*nChain=merg(nChainTemp,nfc);break;case _SYN_WHILE:Match(_SYN_WHILE,"while");nWQUAD=nNXQ;Match(_SYN_LPAREN,"(");Condition(&ntc,&nfc);bp(ntc,nNXQ);Match(_SYN_RPAREN,")");Statement_Block(&nChainTemp);bp(nChainTemp,nWQUAD);sprintf(strTemp,"%d",nWQUAD);gen("j","","",strTemp);*nChain=nfc;break;}return;}void Statement_Sequence(int *nChain) /* 语句串分析函数 */ {Statement(nChain);while (uWord.syn==_SYN_ID || uWord.syn==_SYN_IF|| uWord.syn==_SYN_WHILE) { /* id if while */bp(*nChain,nNXQ);Statement(nChain);}bp(*nChain,nNXQ);return;}void Statement_Block(int *nChain) /* 语句块分析函数 */{Match(_SYN_LEFTBRACKET2,"{");Statement_Sequence(nChain);Match(_SYN_RIGHTBRACKET2,"}");}void Parse(void){int *nChain;Scaner( );Match(_SYN_MAIN,"main");Match(_SYN_LPAREN,"(");Match(_SYN_RPAREN,")");Statement_Block(&nChain);if (uWord.syn!=_SYN_END) fprintf(fw," 源程序非正常结束!");PrintQuaternion( );}void lrparse(void) /* 语法语义分析主函数 */{pQuad=(QUATERNION *) malloc(strlen(strSource) * sizeof(QUATERNION)); nSuffix=0;nfc=ntc=nNXQ=1;fw=fopen(strFileName,"w");Parse( );fclose(fw);}。