编译原理课程设计一个简单编译器的设计与分析
编译原理课程设计C-语言编译器

编译原理课程设计报告课题名称: C-语言编译器设计提交文档学生姓名:李杰提交文档学生学号:0743041240同组成员名单:无指导教师姓名:金军N不指导教师评阅意见:..提交报告时间: 2010年 6 月 10日1.课程设计目标实验建立C-编译器。
只含有scanner和parser部分。
2.分析与设计(1)实现方法:编程语言为C语言。
编程方法:scanner部分根据DFA图用switch-case结构实现状态转换;parser部分用递归下降分析方法实现。
(2)扫描器:C-惯用的词法1、语言的关键字:else if int return void while2、专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */3、其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|94、空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM关键字。
5. 注释用通常的C语言符号/ * . . . * /围起来。
注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。
注释不能嵌套各单词的状态转换图(DFA图如下)词法结构见文件"globals.h"中。
(3)分析器:分析树结构见文件"globals.h"中。
C-的BNF语法如下:(4)代码设计说明:程序结构:语法分析函数parse通过调用词法分析函数getToken实现语法分析。
文件和函数的设计说明:文件main.c包含相应头文件,及main函数的实现;文件golbals.h 包含符号表和分析数的数据结构及在其它文件中使用的变量;文件util.h 和util.c实现与词法分析和语法分析输出相关的函数printToken和printTree,以及分析树节点初始化相关的函数newStmtNode,newExpNode(Expkind)和copyString;文件scan.h 和scan.c实现词法分析,主要函数为getToken;文件parse.h 和parse.c实现语法分析,函数为与文法规则对应的函数。
编译原理编译器课程设计

编译原理编译器课程设计一、课程目标知识目标:1. 理解编译原理的基本概念,掌握编译器各阶段的工作原理和实现方法;2. 学会使用一种编程语言(如C、Java等)编写简单的编译器程序;3. 掌握词法分析、语法分析、语义分析及目标代码生成的基本技术和策略;4. 了解优化技术在编译器中的应用,提高程序运行效率。
技能目标:1. 能够运用所学知识独立设计并实现一个简单的编译器;2. 培养学生运用编译原理知识解决实际问题的能力;3. 提高学生的编程实践能力和团队协作能力;4. 培养学生查阅资料、分析问题、总结归纳的能力。
情感态度价值观目标:1. 培养学生对编译原理和编译器开发工作的兴趣,激发学生的学习热情;2. 培养学生勇于探索、积极创新的精神,增强克服困难的信心和毅力;3. 培养学生具备良好的编程习惯,遵循职业道德,为我国软件产业的发展贡献自己的力量。
本课程旨在通过编译原理编译器课程设计,使学生掌握编译器的基本原理和技术,提高编程实践能力,培养团队协作精神,激发学生的学习兴趣和创新精神。
课程性质为理论与实践相结合,注重培养学生的实际操作能力。
针对学生的年级特点,课程内容将逐步深入,从基本概念到实际应用,引导学生由浅入深地掌握编译器相关知识。
在教学过程中,教师需关注学生的学习进度,及时调整教学策略,确保课程目标的实现。
通过本课程的学习,学生将具备独立设计和实现简单编译器的能力,为后续相关课程的学习打下坚实基础。
二、教学内容1. 编译原理概述:介绍编译器的基本概念、发展阶段和组成部分,使学生了解编译器在整个软件开发过程中的地位和作用。
教材章节:第一章2. 词法分析:讲解词法分析器的功能、设计方法,以及正则表达式和有限自动机等基本概念。
教材章节:第二章3. 语法分析:介绍语法分析器的作用、设计方法,以及上下文无关文法、LL(1)、LR(1)等分析方法。
教材章节:第三章4. 语义分析:讲解语义分析器的任务、属性文法、语法制导翻译等概念,以及类型检查和符号表管理方法。
编译原理课程设计---一个简单编译器的设计与分析

摘要使用过现代计算机的人都知道,多数用户是应用高级语言来实现他们所需要的计算的。
现在计算机系统一般都含有不只一个的高级语言的编译程序,对有些高级语言甚至配置了几个不同性能的编译程序,供用户按不同需要进行选择。
高级语言编译程序是计算机系统软件最主要的组成部分之一,也是用户最直接关系的工具之一。
计算机上执行一个高级语言程序一般分为两步:第一,用一个编译程序把高级语言翻译成机器语言程序;第二,运行所得的机器语言程序求得计算结果。
通常说的翻译程序是指能够把某一种语言程序转换成另一种语言程序(目标语言程序)。
如果源语言诸如Fortran,Pascal,C,Ada或java这样的高级语言,而目标程序是诸如汇编语言或者机器语言这类的低级语言,这样的一个翻译程序就是称为编译程序。
一个编译程序的工作过程一般可以划分为五个阶段:词法分析、语法分析、语义分析与中间代码生成、优化、目标代码生成。
每个阶段都是从上一个阶段得到结果,对他进行分析,并且根据一些外部环境(例如符号表等)得到最终的输出结果。
要构造一个编译程序,可以按照这样的阶段来分别构造,最后来连调。
现在人们已经建立了多种编制部分编译程序或整个编译程序的有效工具。
有些能用于自动生成扫描器(如LEX),有些可以用于自动产生语法分析器(如YACC),有些甚至可以用来自动产生整个的编译程序。
这些构造编译程序的工具成为编译程序-编译程序、编译程序产生器或翻译程序书写系统,他们是按照编译程序和目标语言的形式描述而自动产生编译程序的。
编译程序是一极其庞大而又复杂的系统,掌握它比较苦难。
但是一旦对其掌握,对以后的程序语言设计,系统软件分析,系统软件设计,形式语言研究等方面都是非常有好处的。
关键字:C语言、、编译、扫描器、语法分析一、需求分析给出类C语言(C语言的子集)的词法和语法定义,并根据对应的语法定义写出一些属性文法和语法制导。
根据词法和语法的定义,构造一个编译程序,它主要可以完成如下功能:1、读入某个已经编辑好的类C源程序文件,通过词法分析器,生成二元组,同时检查词法错误;2、语法分析器将产生的二元组作为输入,进行语法分析,同时检查语法错误;3、在语法分析同时,利用属性文法和语法制导技术,产生具体的语意动作,并对符号表进行操作;4、根据语义动作产生整个源程序的四元式序列;5、将产生的四元式序列连同符号表一起输出,作为编译程序的最终输出结果;6、对最后的代码优化和目标代码生成要有所考虑,必须留有一定的接口供以后扩展;7、增大程序的可移植性,努力做到整个系统方便移植。
简单编译器编译原理课设(中版)

目录1 词法分析 (2)1.1 实验目的 (2)1.2 实验要求 (2)1.2.1待分析的简单的词法 (2)1.2.2 各种单词符号对应的种别码: (2)1.2.3 词法分析程序的功能: (3)1.3 词法分析程序的算法思想: (3)1.3.1 主程序示意图: (3)1.3.2 扫描子程序的算法思想: (4)1.3.3 词法分析程序的C语言程序源代码: (6)1.3.4 结果分析: (6)1.3.5 总结: (7)2 语法分析 (8)2.1 实验目的 (8)2.2实验要求 (8)2.2.1 待分析的简单语言的语法 (8)2.2.2 实验算法结构 (8)语法分析程序的算法思想 (8)2.3 结果分析: (13)2.4 总结: (15)3 语义分析程序 (16)3.1 实验目的: (16)3.2 实验要求: (16)3.3 算法思想: (16)3.3.1 程序结构图 (16)3.3.2 设置语义过程 (20)3.3.3 函数lrparser 在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。
在实验中我们只对表达式、赋值语句进行翻译。
(21)3.3.4 简单赋值语句的翻译文法 (21)3.4 结果分析 (22)3.5 总结: (25)1 词法分析(李梦珂 201181216 负责)1.1 实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
1.2 实验要求设计、编制并调试一个词法分析程序,三人一组。
1.2.1待分析的简单的词法(1)关键字:int if then else while do read write所有的关键字都是小写。
(2)运算符和界符::= = + - ++ -- * / < <= != > >= = ; ( ) { } #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
简单编译器课程设计

简单编译器课程设计一、课程目标知识目标:1. 理解编译器的基本概念,掌握编译过程的主要环节;2. 学习简单编译器的构造原理,了解词法分析、语法分析、语义分析的基本方法;3. 掌握一种编程语言的基本语法,如C语言,并能运用所学知识编写简单的编译程序。
技能目标:1. 培养学生运用所学编译原理知识,独立设计并实现简单编译器的能力;2. 培养学生运用编程语言解决实际问题的能力,提高编程实践技能;3. 培养学生团队合作意识,学会与他人共同分析问题、解决问题。
情感态度价值观目标:1. 激发学生对计算机科学领域编译原理的兴趣,提高学生的学习积极性;2. 培养学生勇于面对困难、敢于挑战的精神,增强学生的自信心;3. 培养学生严谨、踏实的科学态度,养成良好的编程习惯。
课程性质:本课程为信息技术学科选修课程,适用于高年级学生。
结合学生特点,课程旨在提高学生的编程能力、逻辑思维能力和团队合作能力。
学生特点:学生已具备一定的编程基础,对编译原理有一定了解,但缺乏实际操作经验。
教学要求:课程要求学生在理解编译原理的基础上,动手实践,独立设计并实现简单编译器。
教师需关注学生的学习进度,及时给予指导,确保课程目标的实现。
通过本课程的学习,学生能够将理论知识与实践相结合,提高自身综合素质。
二、教学内容本课程教学内容分为以下四个部分:1. 编译器基本概念与编译过程- 理解编译器的作用和基本工作原理;- 掌握编译过程的五个阶段:词法分析、语法分析、语义分析、中间代码生成和目标代码生成;- 了解编译器各阶段之间的关系和相互作用。
2. 词法分析- 学习词法分析的基本概念和方法;- 掌握正则表达式、有限自动机等词法分析工具;- 实现简单的词法分析程序。
3. 语法分析- 学习语法分析的基本概念和方法;- 掌握上下文无关文法、递归下降分析、LL(1)分析法等语法分析方法;- 实现简单的语法分析程序。
4. 语义分析与中间代码生成- 学习语义分析的基本概念和方法;- 掌握符号表、类型检查等语义分析方法;- 了解中间代码的种类及其生成方法;- 实现简单的语义分析和中间代码生成程序。
编译原理课程设计___C语言编译器的实现

扬州大学编译原理课程设计学号:*********姓名:专业:计算机科学与技术课程:编译原理指导教师:***目录一.程序简介与分析---------------------------------------------------------3 二.程序适用范围-----------------------------------------------------------3 三.词法分析---------------------------------------------------------------3 四.语法分析---------------------------------------------------------------4 五.语义分析和中间代码生成------------------------------------------------10 六.代码生成--------------------------------------------------------------12 七.流程图----------------------------------------------------------------13 八.实现------------------------------------------------------------------14 九.程序运行结果----------------------------------------------------------14 十.总结------------------------------------------------------------------18 十一.附录(源程序)--------------------------------------------------------18简单的编译程序设计一.程序简介与分析本程序由四个部分组成:词法分析子程序,语法分析子程序,语义分析子程序,目标代码生成程序。
编译原理实现一个简单的编译器

编译原理实现一个简单的编译器在编译原理领域,编译器是一种将源代码转换为目标代码的工具。
本文将探讨如何实现一个简单的编译器,并介绍编译器的基本原理和步骤。
一、引言编译器是计算机科学中的重要概念,它负责将高级语言转换为低级语言,使计算机能够理解和执行程序。
一个完整的编译器通常包括以下几个阶段:词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成。
二、词法分析词法分析是编译器的第一步,它将源代码分解为一个个词法单元(token),并生成 token 流。
常见的词法单元有标识符、关键字、运算符和常量等。
在实现一个简单的编译器时,我们可以使用正则表达式来识别和提取不同类型的词法单元。
例如,使用 `\w+` 来匹配标识符,使用`if|else|while` 来匹配关键字等。
三、语法分析语法分析是编译器的第二步,它根据词法分析生成的 token 流,将其转换为抽象语法树(Abstract Syntax Tree,简称 AST)。
AST 表示了源代码的结构和语法关系。
在实现一个简单的编译器时,我们可以使用上下文无关文法(Context-Free Grammar,简称 CFG)来描述语法规则,然后使用递归下降法(Recursive Descent Parsing)来进行语法分析。
四、语义分析语义分析是编译器的第三步,它对抽象语法树进行分析,检查语法和语义错误,并进行类型推断和类型检查。
语义分析阶段还可以进行符号表的生成和管理。
在实现一个简单的编译器时,我们可以定义语义规则来检查源代码的语义正确性。
例如,检查变量的声明和使用是否匹配,检查表达式的类型是否兼容等。
五、中间代码生成中间代码生成是编译器的第四步,它将抽象语法树转换为一种中间表示形式,通常是三地址码或类似形式。
中间代码是一种介于源代码和目标代码之间的表示形式。
在实现一个简单的编译器时,我们可以使用一组规则来将抽象语法树转换为中间代码。
例如,将控制结构转换为条件跳转语句,将表达式转换为基本的算术运算等。
编译原理分析课程设计

编译原理分析课程设计一、课程目标知识目标:1. 理解编译原理的基本概念,掌握编译过程的主要阶段及其功能;2. 学会使用形式语言和自动机的基本理论分析编程语言的结构;3. 掌握词法分析、语法分析、语义分析的基本方法,并能运用到实际编译器设计中;4. 了解代码生成和优化的一般方法,并能分析其效率。
技能目标:1. 能运用所学编译原理知识,对简单的编程语言进行词法、语法、语义分析;2. 掌握使用编译器生成工具,如lex、yacc等,实现一个小型编程语言的编译器;3. 培养学生独立分析和解决问题的能力,提高编程实践技能。
情感态度价值观目标:1. 激发学生对计算机科学领域的兴趣,培养其探索精神和创新意识;2. 培养学生良好的团队合作意识,使其在学习过程中学会交流、协作、分享;3. 增强学生对我国计算机事业的自豪感,激发其为我国信息技术发展贡献力量的信念。
课程性质分析:本课程为计算机科学与技术专业核心课程,旨在让学生掌握编译原理的基本知识,具备一定的编译器设计和实现能力。
学生特点分析:学生为大学三年级本科生,具备一定的编程基础和离散数学知识,对编译原理有一定了解,但实践经验不足。
教学要求:结合学生特点,注重理论与实践相结合,强调知识的应用和能力的培养,提高学生的编程实践技能和综合素质。
在教学过程中,将课程目标分解为具体的学习成果,以便于教学设计和评估。
二、教学内容1. 编译原理概述:介绍编译器的作用、编译过程及各阶段功能;- 教材章节:第1章 编译原理概述2. 编程语言与文法:分析编程语言的结构,引入文法、语法树等概念;- 教材章节:第2章 编程语言与文法3. 词法分析:讲解词法分析的基本概念,介绍词法分析器的实现方法;- 教材章节:第3章 词法分析4. 语法分析:介绍语法分析的方法,如LL(1)、LR(1)分析法;- 教材章节:第4章 语法分析5. 语义分析:讲解语义分析的作用和基本方法,如类型检查、符号表管理等;- 教材章节:第5章 语义分析6. 中间代码生成与优化:介绍中间代码生成和优化的基本方法;- 教材章节:第6章 中间代码生成与优化7. 代码生成与目标代码优化:讲解目标代码生成和优化的一般方法;- 教材章节:第7章 代码生成与目标代码优化8. 实践环节:设计并实现一个小型编程语言的编译器,涵盖词法、语法、语义分析及代码生成;- 教材章节:附录 实践环节教学内容安排与进度:共16周,每周2课时。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
摘要使用过现代计算机的人都知道,多数用户是应用高级语言来实现他们所需要的计算的。
现在计算机系统一般都含有不只一个的高级语言的编译程序,对有些高级语言甚至配置了几个不同性能的编译程序,供用户按不同需要进行选择。
高级语言编译程序是计算机系统软件最主要的组成部分之一,也是用户最直接关系的工具之一。
计算机上执行一个高级语言程序一般分为两步:第一,用一个编译程序把高级语言翻译成机器语言程序;第二,运行所得的机器语言程序求得计算结果。
通常说的翻译程序是指能够把某一种语言程序转换成另一种语言程序(目标语言程序)。
如果源语言诸如Fortran,Pascal,C,Ada或java这样的高级语言,而目标程序是诸如汇编语言或者机器语言这类的低级语言,这样的一个翻译程序就是称为编译程序。
一个编译程序的工作过程一般可以划分为五个阶段:词法分析、语法分析、语义分析与中间代码生成、优化、目标代码生成。
每个阶段都是从上一个阶段得到结果,对他进行分析,并且根据一些外部环境(例如符号表等)得到最终的输出结果。
要构造一个编译程序,可以按照这样的阶段来分别构造,最后来连调。
现在人们已经建立了多种编制部分编译程序或整个编译程序的有效工具。
有些能用于自动生成扫描器(如LEX),有些可以用于自动产生语法分析器(如YACC),有些甚至可以用来自动产生整个的编译程序。
这些构造编译程序的工具成为编译程序-编译程序、编译程序产生器或翻译程序书写系统,他们是按照编译程序和目标语言的形式描述而自动产生编译程序的。
编译程序是一极其庞大而又复杂的系统,掌握它比较苦难。
但是一旦对其掌握,对以后的程序语言设计,系统软件分析,系统软件设计,形式语言研究等方面都是非常有好处的。
关键字:C语言、、编译、扫描器、语法分析一、需求分析给出类C 语言(C 语言的子集)的词法和语法定义,并根据对应的语法定义写出一些属性文法和语法制导。
根据词法和语法的定义,构造一个编译程序,它主要可以完成如下功能:1、读入某个已经编辑好的类C 源程序文件,通过词法分析器,生成二元组,同时检查词法错误;2、语法分析器将产生的二元组作为输入,进行语法分析,同时检查语法错误;3、在语法分析同时,利用属性文法和语法制导技术,产生具体的语意动作,并对符号表进行操作;4、根据语义动作产生整个源程序的四元式序列;5、将产生的四元式序列连同符号表一起输出,作为编译程序的最终输出结果;6、对最后的代码优化和目标代码生成要有所考虑,必须留有一定的接口供以后扩展;7、增大程序的可移植性,努力做到整个系统方便移植。
二、详细算法设计词法分析程序 → 语法分析程序 → 语义分析程序 →编译器。
三、流程图图II 递归下降分析程序示意图图III 语句块分析示意图图IV 语句串分析示意图图V 语句分析示意图四、相关函数说明void scanner(); //扫描void lrparser();void staBlock(int *nChain); //语句块void staString(int *nChain); //语句串void sta(int *nChain); //语句void fuzhi(); //赋值语句void tiaojian(int *nChain); //条件语句void xunhuan(); //循环语句char* E(); //Expresiion表达式char* T(); //Term项char* F(); //Factor因子char *newTemp(); //自动生成临时变量void backpatch(int p,int t); //回填int merge(int p1,int p2); //合并p1和p2void emit(char *res,char *num1,char *op,char *num2); //生成四元式五.运行结果图VI 赋值语句的分析图VII 条件语句的分析图VIII 循环语句的分析图IX 综合六.编译器使用说明程序提示用户输入字符串“Please input your source string:”,用户输入字符串并以“#”号结束。
回车后,程序显示运行结果。
七.程序清单#include<stdio.h>#include<string.h>#include<math.h>#include<stdlib.h>char prog[80]; /* 存放所有输入字符 */char token[8]; /* 存放词组 */char ch; /* 单个字符 */int syn,p,m,n,i; /* syn:种别编码 */double sum;int count;int isSignal; /* 是否带正负号(0不带,1负号,2正号) */int isError;int isDecimal; /* 是否是小数 */double decimal; /* 小数 */int isExp; /* 是否是指数 */int index; /* 指数幂 */int isNegative; /* 是否带负号 */double temp;int temp2;int repeat; /* 是否连续出现+,- */int nextq;int kk; /* 临时变量的标号 */int ntc,nfc,nnc,nnb,nna;char *rwtab[9]={"main","int","float","double","char","if","else","do","while"}; struct{char result[10]; /* 字符串(字符数组) */char arg1[10];char opera[10];char arg2[10];}fourCom[20]; /* 结构体数组 */void scanner(); /* 扫描 */void lrparser();void staBlock(int *nChain); /* 语句块 */void staString(int *nChain); /* 语句串 */void sta(int *nChain); /* 语句 */void fuzhi(); /* 赋值语句 */void tiaojian(int *nChain); /* 条件语句 */void xunhuan(); /* 循环语句 */char* E(); /* Expresiion表达式 */char* T(); /* Term项 */char* F(); /* Factor因子 */char *newTemp(); /* 自动生成临时变量 */void backpatch(int p,int t); /* 回填 */int merge(int p1,int p2); /* 合并p1和p2 */void emit(char *res,char *num1,char *op,char *num2); /* 生成四元式 */void main(){ p=0;count=0;isDecimal=0;index=0;repeat=0;kk=0;printf("\nPlease input your source string:\n");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;isError=0;scanner();lrparser();for(i=1;i<nextq;i++) /* 循环输出四元式 */{printf("\n%d\t",i);printf("(%5s %5s %5s \t%5s )\n",fourCom[i].arg1,fourCom[i].opera,fourCom[i].arg2,fourCom[i].result);}}void lrparser(){int nChain;nfc=ntc=1;nextq=1;if(syn==1) /* main */{scanner();if(syn==26) /* ( */{ scanner();if(syn==27) /* ) */{ scanner();staBlock(&nChain);}elseprintf("缺少右括号\n");}elseprintf("缺少左括号\n");}elseprintf("缺少main\n");}/* <语句块> ::= '{'<语句串>'}' */void staBlock(int *nChain) /* 语句块 */{ if(syn==28) /* { */{scanner();staString(nChain);/* backpatch(*nChain,nextq); */if(syn==29) /* } */scanner(); /* 读下一个 */elseprintf("缺少}号\n");}elseprintf("缺少{号\n");}/* <语句串>::=<语句>{;<语句>}; */void staString(int *nChain) /* 语句串 */{sta(nChain);backpatch(*nChain,nextq);while(syn==31) /* ; */{scanner();sta(nChain);}/* backpatch(*nChain,nextq-1); */}void sta(int *nChain) /* 语句 */{if(syn==10){fuzhi();/* *nChain=0; */}else if(syn==6) /* if */{tiaojian(nChain);}else if(syn==8) /* do */xunhuan();}/* <条件语句>->if(<条件>)<语句块> */void tiaojian(int *nChain){char res[10],num1[10],num2[10],op[10]; int nChainTemp;/* <条件>-><表达式><关系运算符><表达式> */ if(syn==6) /* if */{scanner();/* strcpy(num1,E()); */if(syn==26) /* ( */{scanner();strcpy(num1,E());if((syn<=37)&&(syn>=32)){switch(syn){case 32:strcpy(op,">");break;case 33:strcpy(op,">=");break;case 34:strcpy(op,"<");break;case 35:strcpy(op,"<=");break;case 36:strcpy(op,"==");break;case 37:strcpy(op,"!=");break;default:printf("error");}}scanner();strcpy(num2,E());strcat(num1,op);strcat(num1,num2);/* nfc=nextq+1; */ntc=nextq; /* 记住if语句位置 */emit("0","if",num1,"goto");nfc=nextq; /* if中表达式为假 */emit("0","","","goto");/* 第一个0已回填 */backpatch(ntc,nextq); /* ntc链接的所有四元式都回填nextq */ }if(syn==27) /* ) */scanner();staBlock(&nChainTemp); /* 语句块 */*nChain=merge(nChainTemp,nfc);}}/* <循环语句>::=do <语句块>while <条件> */void xunhuan(){char res[10],num1[10],num2[10],op[10];int nChainTemp;if(syn==8) /* do */{nnc=nextq; /* 记住if语句位置,emit之后nextq就变了 */ /* emit("0","if",num1,"goto"); */scanner();staBlock(&nChainTemp); /* 语句块 */if(syn==9) /* while */{scanner();if(syn==26) /* ( */{scanner();strcpy(num1,E());if((syn<=37)&&(syn>=32)){switch(syn){case 32:strcpy(op,">");break;case 33:strcpy(op,">=");break;case 34:strcpy(op,"<");break;case 35:strcpy(op,"<=");break;case 36:strcpy(op,"==");break;case 37:strcpy(op,"!=");break;default:printf("error");}}scanner();strcpy(num2,E());strcat(num1,op);strcat(num1,num2);nnb=nextq;backpatch(nnb,nnc);nna=nextq;emit("0","","","goto");backpatch(nna,nextq);}if(syn==27) /* ) */scanner();}}}void fuzhi() /* 赋值语句只有1个操作数 */ {char res[10],num[10]; /* num操作数 */ if(syn==10) /* 字符串 */{strcpy(res,token); /* 结果 */scanner();if(syn==21) /* = */{scanner();strcpy(num,E());emit(res,num,"=","");}else{printf("缺少=号\n");}}}char* E() /* Expression表达式 */{char *res,*num1,*op,*num2;res=(char *)malloc(10);num1=(char *)malloc(10);op=(char *)malloc(10);num2=(char *)malloc(10);strcpy(num1,T());while((syn==22)||(syn==23)) /* + - */ {if(syn==22) /* + */strcpy(op,"+");elsestrcpy(op,"-");strcpy(num2,T());strcpy(res,newTemp());emit(res,num1,op,num2);strcpy(num1,res);}return num1;}char* T() /* Term项 */{char *res,*num1,*op,*num2;res=(char *)malloc(10);num1=(char *)malloc(10);op=(char *)malloc(10);num2=(char *)malloc(10);strcpy(num1,F());while((syn==24)||(syn==25)) /* * / */{if(syn==24)strcpy(op,"*");elsestrcpy(op,"/");scanner();strcpy(num2,F());strcpy(res,newTemp());emit(res,num1,op,num2);strcpy(num1,res);}return num1;}char* F() /* Factor因子 */{char *res;res=(char *)malloc(10);if(syn==10) /* 字符串 */{strcpy(res,token);scanner();}else if(syn==20) /* 二进制数 */{itoa((int)sum,res,10); /* 整数转换为字符串 */ scanner();}else if(syn==26) /* ( */{res=E();if(syn==27) /* ) */{scanner();}else isError=1;}elseisError=1;return res;}char *newTemp(){char *p;char varTemp[10];p=(char *)malloc(10);kk++;itoa(kk,varTemp,10);strcpy(p+1,varTemp);p[0]='T';return p;}/* 将p所链接的每个四元式的第四个分量都回填t */void backpatch(int p,int t){int w,circle=p;while(circle) /* circle不为0的时候 */{w=atoi(fourCom[circle].result); /* 四元式circle第四分量内容 *//* strcpy(fourCom[circle].result,t); //把t填进四元式circle的第四分量 */ sprintf(fourCom[circle].result,"%d",t);circle=w; /* w记录的是链条上下一个四元式,移动! */} return;}int merge(int p1,int p2) /* 合并p1和p2 */{char circle,nResult;if(p2==0)nResult=p1;else{nResult=circle=p2;while(atoi(fourCom[circle].result)) /* 四元式第四个分量不为0 */{circle=atoi(fourCom[circle].result);sprintf(fourCom[circle].result,"%s",p1);} /* 目的是用p1的值覆盖0 */}return nResult; /* p2是头,p1覆盖0,接在p2后边 */}void emit(char *res,char *num1,char *op,char *num2){strcpy(fourCom[nextq].result,res);strcpy(fourCom[nextq].arg1,num1);strcpy(fourCom[nextq].opera,op);strcpy(fourCom[nextq].arg2,num2);nextq++;}void scanner(){sum=0;decimal=0;m=0;for(n=0;n<8;n++)token[n]=NULL;ch=prog[p++]; /* 从prog中读出一个字符到ch中 */while(ch==' '||ch=='\n') /* 跳过空字符(无效输入) */ch=prog[p++];if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) /* ch是字母字符 */{while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch; /* ch=>token */ch=prog[p++]; /* 读下一个字符 */}token[m++]='\0';p--; /* 回退一格 */syn=10; /* 标识符 *//* 如果是"begin","if","then","while","do","end"标识符中的一个 */for(n=0;n<9;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){if(isSignal==1){/* token[m++]='-'; */}while((ch>='0')&&(ch<='9')){sum=sum*10+ch-'0'; /* ch中数字本身是当做字符存放的 */ch=prog[p++];}if(ch=='.'){isDecimal=1;ch=prog[p++];count=0; /* 之前忘了清零,123.123+123.123#两个浮点数就无法识别 */ while((ch>='0')&&(ch<='9')){/* pow(x,y)计算x的y次幂 */temp=(ch-'0')*pow(0.1,++count);decimal=decimal+temp;/* AddToDec(); */ch=prog[p++];}sum=sum+decimal;}if(ch=='e'||ch=='E'){isExp=1;ch=prog[p++];if(ch=='-'){isNegative=1;ch=prog[p++];}while((ch>='0')&&(ch<='9')){/* 指数 */index=index*10+ch-'0';ch=prog[p++];}/* 10的幂 *//* 123e3代表123*10(3) *//* sum=sum*pow(10,index);是错误的 */if(isNegative)sum=sum*pow(0.1,index);elseif(isSignal==1){sum=-sum;isSignal=0;}p--;syn=20;}else switch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=35;token[m++]=ch; }else{syn=34;p--;}break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=33;token[m++]=ch; }else{syn=32;p--;}break;case '=':m=0;token[m++]=ch;ch=prog[p++];syn=36;token[m++]=ch;}else{syn=21;p--;}break;case '+':temp2=prog[p];token[m++]=ch;if((temp2>='0')&&(temp2<='9')&&(repeat==1)){isSignal=2;ch=prog[p++];repeat=0;goto IsNum;}if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) /* 如果重复出现符号,才将后边的+,-视为正负号 */{repeat=1;/* ch=prog[p++]; */}syn=22;break;case '-':temp2=prog[p];token[m++]=ch;if((temp2>='0')&&(temp2<='9')&&(repeat==1)){isSignal=1;ch=prog[p++]; /* 读"-"下一个字符 */repeat=0;goto IsNum; /* 转到数字的识别 */}if(((temp2=='+')||(temp2=='-'))&&(repeat==0)) /* 如果重复出现符号,才将后边的+,-视为正负号 */{repeat=1; /* 预言会重复 *//* ch=prog[p++]; //读下一个字符 */syn=23;break;case '*':temp2=prog[p];token[m++]=ch;if(temp2=='+'){isSignal=2;repeat=1;}else if(temp2=='-') {isSignal=1;repeat=1;}syn=24;break;case '/':syn=25;token[m++]=ch; break;case '(':temp2=prog[p];token[m++]=ch;if(temp2=='+'){isSignal=2;repeat=1;}else if(temp2=='-') {isSignal=1;repeat=1;}syn=26;break;case ')':syn=27;token[m++]=ch; break;case '{':syn=28;token[m++]=ch; break;syn=29;token[m++]=ch;break;case ',':syn=30;token[m++]=ch;break;case ';':syn=31;token[m++]=ch;break;case'#':syn=0;token[m++]=ch;break;default:syn=-1;}getch();}八、总结本次设计的C语言的子集(便于叙述,以后称之为Cxx),是本着简单、易懂、易操作,而且能够完成一定功能的原则,尽量实现最基本的,人们最常用的部分,而抛弃那些不常使用的,或者难以实现的部分。