西安电子科技大学编译原理 (25)
编译原理基础知识
编译原理基础知识编译原理是计算机科学中一门重要的学科,它研究的是将程序源代码转化为可执行代码的过程。
掌握编译原理的基础知识对于理解计算机编程语言的运行原理以及进行高效编程至关重要。
本文将介绍编译原理的基本概念、过程和常用算法。
一、编译原理概述编译器是实现编译原理的工具,它将高级语言代码转化为机器语言代码。
编译器的工作过程可以分为三个主要阶段:词法分析、语法分析和语义分析。
词法分析器主要负责将源代码分解为词法单元,语法分析器则负责将词法单元组织成语法树,而语义分析器则检查语法树的语义错误并进行修正。
二、词法分析词法分析是编译器的第一个阶段,它将源代码分解为词法单元(Token)。
词法单元是程序中的最小可识别单位,如标识符、关键字、运算符等。
词法分析器通常使用有限自动机、正则表达式等方法进行词法单元的识别和分类。
三、语法分析语法分析是编译器的第二个阶段,它将词法单元组织成语法树(Parse Tree)。
语法树是由语法分析器根据源代码的语法规则生成的一棵树状结构。
语法分析器使用上下文无关文法(CFG)来描述语法规则,并通过递归下降、LR分析等算法进行语法单元的解析和组织。
四、语义分析语义分析是编译器的第三个阶段,它主要负责检查语法树的语义错误并进行修正。
语义分析器会检查变量的声明和使用是否一致、类型是否匹配等问题,并生成中间代码或目标代码。
常见的语义分析算法包括类型检查、符号表管理等。
五、代码生成代码生成是编译器的最后一个阶段,它将语义分析阶段生成的中间代码或目标代码转化为可执行代码。
代码生成器会优化代码的执行效率,包括寄存器分配、指令选择、代码重排等。
常用的代码生成算法有静态单赋值(SSA)形式转换、线性扫描代码生成等。
六、总结编译原理是计算机科学中的一门重要学科,它涉及到将源代码转化为可执行代码的过程。
掌握编译原理的基础知识可以帮助我们理解计算机编程语言的运行原理,提高编程效率。
本文介绍了编译原理的概述,包括词法分析、语法分析、语义分析和代码生成等基本概念和过程。
电子科技大学编译原理--A2答案--网络教育
《计算机编译原理》试卷A2参考答案一、单项选择题(每小题1分,共25分)1、构造编译程序应掌握___D___。
A、源程序B、目标语言C、编译方法D、以上三项都是2、变量应当___C___。
A、持有左值B、持有右值C、既持有左值又持有右值D、既不持有左值也不持有右值3、编译程序绝大多数时间花在___D___上。
A、出错处理B、词法分析C、目标代码生成D、管理表格4、___D___不可能是目标代码。
A、汇编指令代码B、可重定位指令代码C、绝对指令代码D、中间代码5、使用___A___可以定义一个程序的意义。
A、语义规则B、词法规则C、产生规则D、词法规则6、词法分析器的输入是___B___。
A、单词符号串B、源程序C、语法单位D、目标程序7、中间代码生成时所遵循的是___C___。
A、语法规则B、词法规则C、语义规则D、等价变换规则8、编译程序是对___D___。
A、汇编程序的翻译B、高级语言程序的解释执行C、机器语言的执行D、高级语言的翻译9、文法G:S→xSx|y所识别的语言是___C___。
A、xyxB、(xyx)*C、x n yx n(n≥0)D、x*yx*10、文法G描述的语言L(G)是指___A___。
A、L(G)={α|S+ ⇒α ,α∈V T*}B、L(G)={α|S*⇒α,α∈V T*}C、L(G)={α|S*⇒α,α∈(V T∪V N*)}D、L(G)={α|S+ ⇒α,α∈(V T∪V N*)}11、有限状态自动机能识别___C___。
A、上下文无关文法B、上下文有关文法C、正规文法D、短语文法12、设G为算符优先文法,G的任意终结符对a、b有以下关系成立___C___。
A、若f(a)>g(b),则a>bB、若f(a)<g(b),则a<bC、A~B都不一定成立D、A~B一定成立13、如果文法G是无二义的,则它的任何句子α___A___。
A、最左推导和最右推导对应的语法树必定相同B、最左推导和最右推导对应的语法树可能不同C、最左推导和最右推导必定相同D、可能存在两个不同的最左推导,但它们对应的语法树相同14、由文法的开始符经0步或多步推导产生的文法符号序列是___C___。
西电编译原理_第二章习题解答
最终的正规式: 1* | 1*(01|0)* = 1*(01|0)*
© 西安电子科技大学 · 软件学院
5
1. 根据模式写出正规式
习题2.4 (2) 所有不含有子串 011 的01串 思路2:考虑包含 011 的串,然后构造没有011的串 ① 含有 子串 011 的最简单的串:
© 西安电子科技大学 · 软件学院
?
| (01|10) (00|11)* (01|10) )*
4
1. 根据模式写出正规式
习题2.4 (2) 所有不含有子串 011 的01串 思路1:简单例子,观察规律 (1) 最简单的串: 0 , 1, 11, 00, 10, 01, 010, …
(2) 上述各串重复: (0 | 00 | 01 | 010 )* = (01 | 0)*
© 西安电子科技大学 · 软件学院
7
2.依据NFA/DFA,给出正规式
思路1: 回顾“正规式 与 FA的关系”
正规集 描述 正规式 识别 有限自动机
正规式、FA是从两个不同的侧面表示一个集合(即正 规集)。所以,根本的方法是以正规集为桥梁, - 先分析清楚 FA 识别的集合之结构特征, - 然后再设计此集合的正规式。
© 西安电子科技大学 · 软件学院
2
1. 根据模式写出正规式
一般思路:(1)分析题意 (2)列举一些最简单的例子 (3)寻找统一规律*,考虑所有可能情况**
习题2.4 (1) 由偶数个0和奇数个1构成的01串
解:① 最简单的串有 0个0和1个1组成的串: 1 2个0和1个1组成的串:010 ,001,100 ② 在上述串的中间、两头添加偶数个0和/或偶数个1,即可 得到满足题意的其他串。 设偶数个0/偶数个1组成的串,可用正规式 A 表示,则最 终正规式: A1A | A0A1A0A
电子科技大学编译原理--B答案--网络教育
《计算机编译原理》试卷B参考答案一、单项选择题(每小题1分,共25分)1、有文法G:E→E*T|TT→T+i|i句子1+2*8+6按该文法G归约,其值为___B___。
A、23B、42C、30D、172、规范归约指___B___。
A、最左推导的逆过程B、最右推导的逆过程C、规范推导D、最左归约的逆过程3、词法分析所依据的是___B___。
A、语义规则B、构词规则C、语法规则D、等价变换规则4、词法分析器的输出结果是___C___。
A、单词的种别编码B、单词在符号表中的位置C、单词的种别编码和自身值D、单词自身值5、正规式M1和M2等价是指___C___。
A、M1和M2的状态数相等B、M1和M2的有向弧条数相等C、M1和M2所识别的语言集相等D、M1和M2状态数和有向弧条数相等6、下面的状态转换图接受的字集为___D___。
A、以0开头的二进制数组成的集合B、以0结尾的二进制数组成的集合C、含奇数个0的二进制数组成的集合D、含偶数个0的二进制数组成的集合7、词法分析器作为独立的阶段使整个编译程序结构更加简洁、明确,因此,___B___。
A、词法分析器应作为独立的一遍B、词法分析器作为子程序较好C、词法分析器分解为多个过程,由语法分析器选择使用D、词法分析器并不作为一个独立的阶段8、若a为终结符,则A→α·aβ为___B___项目A、归约B、移进C、接受D、待约9、若项目集I k含有A→α·,则在状态k时,仅当面临的输入符号a∈FOLLOW(A)时,才采取“A→α·”动作的一定是___D___。
A、LALR文法B、LR(0)文法C、LR(1)文法D、SLR(1)文法10、就文法的描述能力来说,有___C___。
A、SLR(1)⊂LR(0)B、LR(1)⊂LR(0)C、SLR(1)⊂LR(1)D、无二义文法⊂LR(1)11、在LR(0)的ACTION子表中,如果某一行中存在标记“r j”的栏,则___A___。
电子科技大学14秋《计算机编译原理》在线作业2答案
14秋《计算机编译原理》在线作业2单选题多选题判断题一、单选题(共15 道试题,共75 分。
)1. 描述一个语言的文法是。
A. 唯一的B. 不唯一的C. 可能唯一D. 可能不唯一-----------------选择:B2. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类:采用自顶向下分析方法时,要求文法中不含有()。
A. 右递归B. 左递归C. 直接右递归D. 直接左递归-----------------选择:B3. 算符文法是指()的文法。
①没有形如U::=...VW...的规则(U,V,W ∈VN)②终结符号集VT中任意两个符号对之间至多有一种优先关系成立③没有相同的规则右部④没有形如U::= ε的规则。
A. ①B. ①②C. ①②③D. ①②③④-----------------选择:A4. 如果文法G是无二义的,则它的任何句子α()。
A. 最左推导和最右推导对应的语法树必定相同B. 最左推导和最右推导对应的语法树可能不同C. 最左推导和最右推导必定相同D. 可能存在两个不同的最左推导,但它们对应的语法树相同-----------------选择:A5. 同心集合并有可能产生新的()冲突A. 归约B. “移进”/“移进”C. “移进”/“归约”D. “归约”/“归约”-----------------选择:D6. SLR(1)分析法的名字中,“R”的含义是()。
A. 自左向右进行分析B. 自右向左进行分析C. 采用最右推导的逆过程——最左归约。
7西安电子科技大学《编译原理》
3.5.1 自下而上分析的基本方法
思路:从句子ω开始,从左到右扫描ω,反复用产生式的左部替换 产生式的右部、谋求对ω的匹配,最终得到文法的开始符号,或者 发现一个错误。
3.5.1.1 规范归约与“剪句柄”
定义3.13 设αβδ是文法G的一个句型, 若 存在S =*>αAδ,A =+>β, 则 称β是句型αβδ相对于A的短语, 特别的,若 有A→β, A→β 则 称β是句型αβδ相对于产生式A→β的直接短语。 一个句型的最左直接短语被称为句柄。 ■ ① 直观上,句型是一个完整结构,短语是句型中的某部分(针对 某非终结符)。S是一个句型,而不是一个短语(树根不是短语)。 ② 短语形成的两个要素: 1.从S可以推导出A,即S=*>αAδ; 2.从A至少一次推导出β,即A=+>β。
13
结
束
上节主要内容: 1. 自下而上分析的基本方法:归约(短语、直接短语、句柄、规 范(最左)归约) 2. 规范归约的形象表示-剪句柄; 3. 移进-归约分析工作模式:格局与格局变换 4. LR分析与LR文法: <1> 分析表:动作表与转移表 <2> 模拟算法:改变格局的两个重要动作-移进与归约 <3> LR分析器的实例分析 <4> LR文法
5
3.5.1.2 移进-归约分析器工作模式
移进-归约分析器的工作模式:
输入记号流 ip top 符 号 状 态 栈 驱动器 移进-归约 分析表 输出
与预测分析对比:
输入记号流 符 top 号 栈 ip 输出
驱动器 预测分析表 (b) 预测分析器模型
预测分析器: 移进-归约分析器: 1.分析方法:格局与格局变换 1. 分析方法:格局与格局变换 2.分析表 2. 分析表 3. 驱动器(模拟算法) 3. 驱动器(模拟算法) 4. LR(文法、语言、分析器) 4. 预测分析表的构造 5. LL(文法、语言、分析器) 5. SLR分析表的构造
编译原理
习惯称法 汇编语言-机器指令:汇编(或交叉汇编) 程序设计语言-汇编语言或机器指令:编译(或解释) 高级语言之间:转换(或预编译) 逆向:反汇编、反编译
19
1.3 编译器与解释器
语言翻译的两种基本形态 先翻译后执行
源程序 编译器 目标程序 输出
边翻译边执行
源程序 输入数据
解释器
1.4 编译器的工作原理与基本组成
position = initial + rate 60
词法分析器
• 标识符position形成的记号是<id, 1> • id是标识符的总称 • 1代表position在符号表中的条目 • 符号表的条目用来存放标示符的 各种属性
• 赋值号=形成的记号是<assign> id, 1 = id, 2 + id, 3 60 •该记号只有一个实例,不需 要属性值来区分实例 •为了直观,记作<=> 符 号 表 • 标识符initial形成的记号是<id,2> 1 position ...
Java 处 理 过 程
计算机能够识别的语言
2
课程简介
翻译
汉语普通话
课程简介
高级程序设计语言
编译 (解释)
处 理 过 程
C 处 理 过 程
C++ 处 理 过 程
Java 处 理 过 程
My PL 处 理 过 程
计算机能够识别的语言
课程简介 介绍编 译器的 原理和 基本实 现方法
源程序 词法分析 语法分析 符 号 表 管 理 语义分析 中间代码生成 代码优化 目标代码生成 目标代码
17
1.1 从面向机器的语言到面向人类的语言
西电_编译原理上机报告
编译原理上机报告《DBMS的设计与实现》学号:姓名:手机:邮箱:完成时间:2013 年6月21日目录1.项目概况 (3)1.1基本目标 (3)1.2完成情况 (3)2.项目实现方案 (4)2.1逻辑结构与物理结构 (4)2.2语法结构与数据结构 (7)2.3执行流程 (19)2.4功能测试 (39)3.总结与未来工作 (48)3.1未完成功能 (48)3.2未来实现方案 (48)1.项目概况1.1 基本目标设计并实现一个DBMS原型系统,可以接受基本的SQL语句,对其进行词法分析、语法分析,然后解释执行SQL语句,完成对数据库文件的相应操作,实现DBMS的基本功能。
1.2 完成情况1.CREATE DATABASE 创建数据库2.SHOW DATABASES 显示数据库名3.DROP DATABASE 删除数据库E DATABASE 选择数据库5.CREATE TABLE 创建表6.SHOW TABLES 显示表名7.DROP TABLE 删除表8.INSERT 插入元组9.SELECT 查询元组10.DELETE 删除元组11.UPDATE 更新元组12.EXIT 退出系统2.项目实现方案2.1 逻辑结构与物理结构1.逻辑结构(1)系统数据库1)元数据的逻辑结构在我设计的系统数据库中,虽然建有元数据的文件,但是文件中没有任何数据,所以元数据的逻辑结构不存在。
2)基本数据的逻辑结构表1 系统数据库的基本数据的逻辑结构(2)用户数据库1)元数据的逻辑结构由于在我的设计中,为数据库中每个表创建一个基本数据文件,所以不需要ppt中的“起始页”,添加了一个“表中列的数目”的列,如下表所示:说明:表中col_type列,取值为整数,1表示字符串,2表示整型2)基本数据的逻辑结构与ppt中的参考方案不同的是,对于数据库中的每一个表,我并不是把每个表的基本数据均存放在一个与数据库同名的基本数据文件中,而是为每个表创建一个与表同名的基本数据文件。
电子科技大学编译原理--A1答案--网络教育
《计算机编译原理》试卷A1参考答案一、单项选择题(每小题1分,共25分)1、语言是___A___A、句子的集合B、产生式的集合C、符号串的集合D、句型的集合2、编译程序前三个阶段完成的工作是___C___A、词法分析、语法分析和代码优化B、代码生成、代码优化和词法分析C、词法分析、语法分析、语义分析和中间代码生成D、词法分析、语法分析和代码优化3、一个句型中称为句柄的是该句型的最左___D___A、非终结符号B、短语C、句子D、直接短语4、下推自动机识别的语言是___C___A、0型语言B、1型语言C、2型语言D、3型语言5、扫描器所完成的任务是从字符串形式的源程序中识别出一个个具有独立含义的最小语法单位即___B___A、字符B、单词C、句子D、句型6、对应Chomsky四种文法的四种语言之间的关系是___B___A、L0⊂L1⊂L2⊂L3B、L3⊂L2⊂L1⊂L0C、L3=L2⊂L1⊂L0D、L0⊂L1⊂L2=L37、词法分析的任务是___A___A、识别单词B、分析句子的含义C、识别句子D、生成目标代码8、常用的中间代码形式不含___D___A、三元式B、四元式C、逆波兰式D、语法树9、代码优化的目的是___C___A、节省时间B、节省空间C、节省时间和空间D、把编译程序进行等价交换10、代码生成阶段的主要任务是___C___A、把高级语言翻译成汇编语言B、把高级语言翻译成机器语言C、把中间代码变换成依赖具体机器的目标代码D、把汇编语言翻译成机器语言11、一个上下文无关文法G包括四个组成部分:一组终结符,一组非终结符,一个开始符号,以及一组___B___。
A、字符串B、产生式C、数字符号D、文法12、程序的基本块是指___D___。
A、一个子程序B、一个仅有一个入口和一个出口的语句C、一个没有嵌套的程序段D、一组顺序执行的程序段,仅有一个入口和一个出口13、高级语言编译程序常用的语法分析方法中,递归下降分析法属于___B___分析方法。
电子科技大学编译原理--A1答案--网络教育
《计算机编译原理》试卷A1参考答案一、单项选择题(每小题1分,共25分)1、语言是___A___A、句子的集合B、产生式的集合C、符号串的集合D、句型的集合2、编译程序前三个阶段完成的工作是___C___A、词法分析、语法分析和代码优化B、代码生成、代码优化和词法分析C、词法分析、语法分析、语义分析和中间代码生成D、词法分析、语法分析和代码优化3、一个句型中称为句柄的是该句型的最左___D___A、非终结符号B、短语C、句子D、直接短语4、下推自动机识别的语言是___C___A、0型语言B、1型语言C、2型语言D、3型语言5、扫描器所完成的任务是从字符串形式的源程序中识别出一个个具有独立含义的最小语法单位即___B___A、字符B、单词C、句子D、句型6、对应Chomsky四种文法的四种语言之间的关系是___B___A、L0⊂L1⊂L2⊂L3B、L3⊂L2⊂L1⊂L0C、L3=L2⊂L1⊂L0D、L0⊂L1⊂L2=L37、词法分析的任务是___A___A、识别单词B、分析句子的含义C、识别句子D、生成目标代码8、常用的中间代码形式不含___D___A、三元式B、四元式C、逆波兰式D、语法树9、代码优化的目的是___C___A、节省时间B、节省空间C、节省时间和空间D、把编译程序进行等价交换10、代码生成阶段的主要任务是___C___A、把高级语言翻译成汇编语言B、把高级语言翻译成机器语言C、把中间代码变换成依赖具体机器的目标代码D、把汇编语言翻译成机器语言11、一个上下文无关文法G包括四个组成部分:一组终结符,一组非终结符,一个开始符号,以及一组___B___。
A、字符串B、产生式C、数字符号D、文法12、程序的基本块是指___D___。
A、一个子程序B、一个仅有一个入口和一个出口的语句C、一个没有嵌套的程序段D、一组顺序执行的程序段,仅有一个入口和一个出口13、高级语言编译程序常用的语法分析方法中,递归下降分析法属于___B___分析方法。
电子科技大学-计算机学院-编译原理实验-语法分析
// SyntaxAnalyzer.cpp : 定义控制台应用程序的入口点。
//#include<stdio.h>#include<string.h>#include<Windows.h>#define MAX_COUNT 1024#define SIGN_UNDEFINED_ERR 1#define SIGN_REDEFINED_ERR 2#define SIGN_EXECUTE_ERR 3#define NO_SIGN_ERR 4#define SIGN_RESERVE_ERR 5#define NO_PARA_ERR 6/*types是支持类型的集合*/typedef enum{ integer } types;/*记录变量信息的结构体*/typedef struct {char vname[17];char vproc[17];bool vkind;types vtype;int vlev;int vadr;} varRecord;/*记录过程信息的结构体*/typedef struct{char pname[17];types ptype;int plev;int varNum;int fadr;int ladr;int parameter;bool parameterIsDefined;} proRecord;/**********文法产生式如下**********A:程序A->BB:分程序B->begin C;M endC:说明与句表C->DC'C'->;DC'|εD:说明语句D->E|JE:变量说明E->integer FF:变量F->GG:标识符G->HG'G'->HG'|IG'|εH:字母H->a|...|z|A|...|ZI:数字I->0|1|...|9J:函数说明J->integer function G(K);L K:参数K->FL:函数体L->begin C;M endM:执行语句表M->NM'M'->;NM'|εN:执行语句N->O|P|Q|WO:读语句O->read(F)P:写语句P->write(F)Q:赋值语句Q->F:=RR:算术表达式R->SR'R'->-SR'|εS:项S->TS'S'->*TS'|εT:因子T->F|U|ZU:常数U->VV:无符号整数V->IV'V'->IV'|εW:条件语句W->if X then N else NX:条件表达式X->RYRY:关系运算符Y-><|<=|>|>=|=|<>Z:函数调用Z->G(R)**********************************/void A();void B();void C();void C_();void D();void E();void F();void G();void J();void K();void L();void M();void M_();void N();void O();void P();void Q();void R();void R_();void S();void S_();void T();void U();void W();void X();void Y();void Z();/*初始化函数:从输入文件读取数据,建立各个文件,初始化全局变量*/bool init(int argc, char* argv[]);/*结束处理函数,将var和pro数组中的元素输出到相应文件,填充输出文件*/ bool final();/*错误处理函数,参数分别为行号、错误码和错误符号*/bool error(int lineNum, int errNum, const char* sign);/*获得所处目录路径,包括最后斜杠,或者为空*/void getPath(char* in, char* out);/*获得文件名,不包括扩展*/void getFilename(char* in, char* out);/*获得下一符号,true表示已到队尾,false表示还未到队尾*/bool nextToken();/*获得当前符号的下一字符,true表示已到'\0'*/bool nextChar();/*判断变量是否已存在*/bool isVarExisted(char* vname, char* vproc, bool vkind);/*判断过程是否已存在,参数为过程名*/bool isProExisted(char* vname);/*获得下一符号,指针不变*/int getNextToken();char input[MAX_COUNT][17];//存放输入文件所有符号的数组int kind[MAX_COUNT];int inputCount;//输入符号的数量int pToken;//指向当前输入符号int pChar;//指向当前输入符号中的当前字符varRecord currentVar;//存放当前变量的信息proRecord currentPro;//存放当前过程的信息int lineNum;//当前行号varRecord var[MAX_COUNT];//存放变量名表项数组proRecord pro[MAX_COUNT];//存放过程名表项数组int varCount;//变量的数量int proCount;//过程的数量FILE* inFile;//输入文件句柄FILE* outFile;//输出文件句柄FILE* errFile;//错误文件句柄FILE* varFile;//变量文件句柄FILE* proFile;//过程文件句柄/*主函数*/int main(int argc, char* argv[]){if (init(argc, argv)){A();final();}return 0;}bool init(int argc, char* argv[]){if (argc != 2){return false;}else{char* inFilename = argv[1];char outFilename[MAX_COUNT] = "";char errFilename[MAX_COUNT] = "";char varFilename[MAX_COUNT] = "";char proFilename[MAX_COUNT] = "";char filename[MAX_COUNT] = "";char path[MAX_COUNT] = "";//获得文件名(不包括扩展名)和路径getFilename(inFilename, filename);getPath(inFilename, path);//生成输出文件全部路径strcat(outFilename, path);//strcat(outFilename, "\\");strcat(outFilename, filename);strcat(outFilename, ".dys");//生成错误文件全部路径strcat(errFilename, path);//strcat(errFilename, "\\");strcat(errFilename, filename);strcat(errFilename, ".err");//生成变量文件全部路径strcat(varFilename, path);//strcat(varFilename, "\\");strcat(varFilename, filename);strcat(varFilename, ".var");//生成过程文件全部路径strcat(proFilename, path);//strcat(proFilename, "\\");strcat(proFilename, filename);strcat(proFilename, ".pro");//打开文件句柄if ((inFile = fopen(inFilename, "r")) && (outFile = fopen(outFilename, "w")) && (errFile = fopen(errFilename, "w")) && (varFile = fopen(varFilename, "w")) && (proFile = fopen(proFilename, "w"))){//初始化单词指针、字符指针、行号、层次inputCount = 0;pToken = 0;pChar = 0;lineNum = 1;//当前行号//level = 0;//当前层次//varCountInPro = 0;strcpy(currentPro.pname, "");currentPro.plev = 0;currentPro.varNum = 0;currentPro.parameter = -1;varCount = 0;proCount = 0;//读取输入文件内容,初始化input数组while (!feof(inFile)){char stringOfLine[MAX_COUNT];if (fgets(stringOfLine, MAX_COUNT, inFile)){char lineString[20] = "";strncpy(lineString, stringOfLine, 19);char* kindString = strrchr(lineString, ' ');kind[inputCount] = atoi(kindString+1);char string[17] = "";strncpy(string, stringOfLine, 16);char* lastString = strrchr(string, ' ');strcpy(input[inputCount], lastString + 1);inputCount++;}}return true;}else{fclose(inFile);fclose(outFile);fclose(errFile);fclose(varFile);fclose(proFile);return false;}}}bool final(){for (int i = 0; i < varCount; i++){int vkind = var[i].vkind ? 1 : 0;char* vtype = (var[i].vtype == integer) ? "integer" : "";fprintf(varFile, "%16s %16s %d %s %d %d\n", var[i].vname, var[i].vproc, vkind, vtype, var[i].vlev, var[i].vadr);}for (int i = 0; i < proCount; i++){char* ptype = (pro[i].ptype == integer) ? "integer" : "";fprintf(proFile, "%16s %s %d %d %d\n", pro[i].pname, ptype, pro[i].plev, pro[i].fadr, pro[i].ladr);}if (fseek(inFile, 0, 0) == 0){while (!feof(inFile))fputc(fgetc(inFile), outFile);}bool val;val = fclose(inFile);val = fclose(outFile);val = fclose(errFile);val = fclose(varFile);val = fclose(proFile);return val;}bool error(int errNum,const char* symbol){char* errInfo;switch (errNum){case SIGN_UNDEFINED_ERR:fprintf(errFile, "***LINE:%d %s符号无定义\n", lineNum, input[pToken]);break;case SIGN_REDEFINED_ERR:fprintf(errFile, "***LINE:%d %s符号重定义\n", lineNum, input[pToken]);break;case SIGN_EXECUTE_ERR:fprintf(errFile, "***LINE:%d %s处不能匹配执行语句\n", lineNum, input[pToken]);break;case NO_SIGN_ERR:fprintf(errFile, "***LINE:%d %s处缺少%s\n", lineNum,input[pToken], symbol);break;case SIGN_RESERVE_ERR:errInfo = "以保留字开头";break;case NO_PARA_ERR:fprintf(errFile, "***LINE:%d 缺少形参%s的声明\n", lineNum, symbol);break;default:errInfo = "未知错误";}return true;}void getPath(char* in, char* out){char* name;name = strrchr(in, '\\');if (name != NULL)strncpy(out, in, strlen(in) - strlen(name) + 1);elsestrcpy(out, "");}void getFilename(char* in, char* out){char* fullName;char* extension;fullName = strrchr(in, '\\');extension = strrchr(in, '.');if (fullName != NULL)strncpy(out, fullName + 1, strlen(fullName) - 1 - strlen(extension));elsestrncpy(out, in, strlen(in) - strlen(extension));}bool nextToken(){pToken++;pChar = 0;if (strcmp(input[pToken], "EOF") == 0){return true;}while (strcmp(input[pToken], "EOLN") == 0){pToken++;lineNum++;}return false;}bool nextChar(){if (input[pToken][pChar] == '\0'){//nextToken();return true;}pChar++;return false;}bool isVarExisted(char* vname, char* vproc, bool vkind){for (int i = 0; i < varCount; i++){if ((strcmp(vname, var[i].vname) == 0) && (strcmp(vproc, var[i].vproc) == 0) && (var[i].vkind == vkind))return true;}for (int i = 0; i < proCount; i++){if (strcmp(vname, pro[i].pname) == 0)return true;}return false;}bool isProExisted(char* vname){for (int i = 0; i < varCount; i++){if (strcmp(vname, var[i].vname) == 0)return true;}for (int i = 0; i < proCount; i++){if (strcmp(vname, pro[i].pname) == 0)return true;}return false;}int getNextToken(){int pNextToken = pToken + 1;while (strcmp(input[pNextToken], "EOLN") == 0) {pNextToken++;}return pNextToken;}void A(){B();}void B(){if (strcmp(input[pToken], "begin") == 0){nextToken();}else{error(NO_SIGN_ERR,"begin");if (strcmp(input[pToken], "integer")!=0){nextToken();}}C();if (strcmp(input[pToken], ";") == 0){nextToken();}{error(NO_SIGN_ERR, ";");if ((strcmp(input[pToken], "integer") != 0) && (strcmp(input[pToken], "read") != 0) && (strcmp(input[pToken], "write") != 0) && (kind[pToken]!=10)){nextToken();}}M();if (strcmp(input[pToken], "end") == 0){nextToken();}else{error(NO_SIGN_ERR, "end");}}void C(){D();C_();}void C_(){if (strcmp(input[pToken], ";") == 0 && strcmp(input[getNextToken()], "integer") == 0) {nextToken();D();C_();}else{if (strcmp(input[pToken], "integer") == 0){error(NO_SIGN_ERR, ";");D();C_();}}void D(){if (strcmp(input[pToken + 1], "function") == 0) {J();}else{E();}}void E(){if (strcmp(input[pToken], "integer") == 0){nextToken();}else{error(NO_SIGN_ERR, "integer");//if (kind[pToken] != 10)//{nextToken();//}}strcpy(currentVar.vname, input[pToken]);strcpy(currentVar.vproc, currentPro.pname);if (pToken == currentPro.parameter){currentVar.vkind = true;currentPro.parameterIsDefined = true;}else{currentVar.vkind = false;}currentVar.vtype = integer;currentVar.vlev = currentPro.plev;currentVar.vadr = varCount;if (isVarExisted(input[pToken], currentPro.pname, currentVar.vkind))//如果存在变量{error(SIGN_REDEFINED_ERR,NULL);}else{if (currentPro.varNum == 0)//如果当前过程中变量数为0,则当前变量是当前过程的第一个变量{currentPro.fadr = currentVar.vadr;}dr = currentVar.vadr;//过程中最后一个变量在变量表中的位置currentPro.varNum++;//过程中变量数++var[varCount] = currentVar;//当前变量存入var数组varCount++;//变量数++}F();}void F(){G();}void G(){if (kind[pToken] == 10){nextToken();}/*char* keywords[] = { "begin", "end", "integer", "if", "then", "else", "function", "read", "write" };int keywordLength[] = { 5, 3, 7, 2, 4, 4, 8, 4, 5 };for (int i = 0; i < 9; i++){if (strncmp(input[pToken], keywords[i], keywordLength[i]) == 0){error(SIGN_RESERVE_ERR);}}H();nextToken();*/}void J(){proRecord proBackup = currentPro;//备份当前过程,在匹配完G过程后恢复if (strcmp(input[pToken], "integer") == 0){nextToken();}else{error(NO_SIGN_ERR, "integer");if (strcmp(input[pToken], "function") != 0){nextToken();}}if (strcmp(input[pToken], "function") == 0){nextToken();}else{error(NO_SIGN_ERR, "function");if (kind[pToken] != 10){nextToken();}}strcpy(currentPro.pname, input[pToken]);currentPro.ptype = integer;currentPro.plev++;currentPro.varNum = 0;currentPro.parameterIsDefined = false;if (isProExisted(input[pToken])){error(SIGN_REDEFINED_ERR,NULL);}if (strcmp(input[pToken], "(") == 0){nextToken();}else{error(NO_SIGN_ERR, "(");if (kind[pToken] != 10){nextToken();}}/*strcpy(currentVar.vname, input[pToken]); strcpy(currentVar.vproc, currentPro.pname); currentVar.vkind = true;currentVar.vtype = integer;currentVar.vlev = currentPro.plev; currentVar.vadr = varCount;*/currentPro.parameter = pToken;K();/*if (currentPro.varNum == 0){currentPro.fadr = currentVar.vadr;}dr = currentVar.vadr; currentPro.varNum++;var[varCount] = currentVar;varCount++;*/if (strcmp(input[pToken], ")") == 0){nextToken();}else{error(NO_SIGN_ERR, ")");if (strcmp(input[pToken], ";") != 0){nextToken();}}if (strcmp(input[pToken], ";") == 0){nextToken();}else{error(NO_SIGN_ERR, ";");if (strcmp(input[pToken], "begin") != 0){nextToken();}}L();currentPro = proBackup;//匹配完G过程后恢复原过程}void K(){F();}void L(){if (strcmp(input[pToken], "begin") == 0){nextToken();}else{error(NO_SIGN_ERR, "begin");if (strcmp(input[pToken], "integer") != 0){nextToken();}}C();if (!currentPro.parameterIsDefined){error(NO_PARA_ERR, input[currentPro.parameter]);}pro[proCount] = currentPro;//在这里而不是在J()函数最后把currentPro加入pro数组是因为M 中可能会使用当前过程(递归)proCount++;if (strcmp(input[pToken], ";") == 0){nextToken();}else{error(NO_SIGN_ERR, ";");if ((strcmp(input[pToken], "integer") != 0) && (strcmp(input[pToken], "read") != 0) && (strcmp(input[pToken], "write") != 0) && (kind[pToken] != 10)){nextToken();}}M();if (strcmp(input[pToken], "end") == 0){nextToken();}else{error(NO_SIGN_ERR, "end");if ((strcmp(input[pToken], ";") != 0) && (strcmp(input[pToken], "end") != 0)){nextToken();}}/*if (strcmp(input[pToken], "begin") == 0){nextToken();C();pro[proCount] = currentPro;//在这里而不是在J()函数最后把currentPro加入pro数组是因为M中可能会使用当前过程(递归)proCount++;if (strcmp(input[pToken], ";") == 0)nextToken();M();if (strcmp(input[pToken], "end") == 0){nextToken();}else{error(SIGN_MATCH_ERR);}}else{error(SIGN_MATCH_ERR);}}else{error(SIGN_MATCH_ERR);}*/}void M(){N();M_();}void M_(){if (strcmp(input[pToken], ";") == 0){nextToken();N();M_();}else{//if ((strcmp(input[pToken], "read") == 0) || (strcmp(input[pToken], "write") == 0)||(strcmp(input[pToken], "if") == 0)||(kind[pToken] == 10))if ((strcmp(input[pToken], "end") != 0) && (strcmp(input[pToken],"EOF") !=0 ))error(NO_SIGN_ERR, ";");N();M_();}}}void N(){if (strcmp(input[pToken], "read") == 0){O();}else if (strcmp(input[pToken], "write") == 0) {P();}else if (strcmp(input[pToken], "if") == 0){W();}else if (kind[pToken] == 10){Q();}else{error(SIGN_EXECUTE_ERR, NULL);nextToken();}}void O(){if (strcmp(input[pToken], "read") == 0){nextToken();}else{error(NO_SIGN_ERR, "read");if (strcmp(input[pToken], "(") != 0)nextToken();}}if (strcmp(input[pToken], "(") == 0){nextToken();}else{error(NO_SIGN_ERR, "(");if (kind[pToken] != 10){nextToken();}}if(!isVarExisted(input[pToken], currentPro.pname, false) && !isVarExisted(input[pToken], currentPro.pname, true)){error(SIGN_UNDEFINED_ERR,NULL);}F();if (strcmp(input[pToken], ")") == 0){nextToken();}else{error(NO_SIGN_ERR, ")");if ((strcmp(input[pToken], ";") != 0) && (strcmp(input[pToken], "end") != 0)){nextToken();}}}void P(){if (strcmp(input[pToken], "write") == 0){nextToken();}else{error(NO_SIGN_ERR, "write");if (strcmp(input[pToken], "(") != 0){nextToken();}}if (strcmp(input[pToken], "(") == 0){nextToken();}else{error(NO_SIGN_ERR, "(");if (kind[pToken] != 10){nextToken();}}if(!isVarExisted(input[pToken], currentPro.pname, false) && !isVarExisted(input[pToken], currentPro.pname, true)){error(SIGN_UNDEFINED_ERR,NULL);}F();if (strcmp(input[pToken], ")") == 0){nextToken();}else{error(NO_SIGN_ERR, ")");if ((strcmp(input[pToken], ";") != 0) && (strcmp(input[pToken], "end") != 0)){nextToken();}}}void Q(){if(!isVarExisted(input[pToken], currentPro.pname, false) && !isVarExisted(input[pToken], currentPro.pname, true) && !isProExisted(input[pToken])){error(SIGN_UNDEFINED_ERR,NULL);}F();if (strcmp(input[pToken], ":=") == 0){nextToken();}else{error(NO_SIGN_ERR, ":=");if ((kind[pToken] != 10) && (kind[pToken] != 11)){nextToken();}}R();}void R(){S();R_();}void R_(){if (strcmp(input[pToken], "-") == 0){nextToken();S();R_();}else{if ((kind[pToken] == 10) || (kind[pToken] == 11)){S();R_();}}}void S(){T();S_();}void S_(){if (strcmp(input[pToken], "*") == 0){nextToken();T();S_();}else{if ((kind[pToken] == 10) || (kind[pToken] == 11)){T();S_();}}}void T(){if (input[pToken][pChar] >= '0' && input[pToken][pChar] <= '9'){U();}else if (strcmp(input[getNextToken()], "(") == 0)///////////////////////pToken+1 {Z();}else{if (!isVarExisted(input[pToken], currentPro.pname, false)&& !isVarExisted(input[pToken], currentPro.pname, true)){error(SIGN_UNDEFINED_ERR,NULL);}F();}}void U(){if (kind[pToken] == 11){nextToken();}}void W(){if (strcmp(input[pToken], "if") == 0){nextToken();}else{error(NO_SIGN_ERR, "if");if ((kind[pToken] != 10) && (kind[pToken] != 11)){nextToken();}}X();if (strcmp(input[pToken], "then") == 0){nextToken();}else{error(NO_SIGN_ERR, "then");if ((strcmp(input[pToken], "integer") != 0) && (strcmp(input[pToken], "read") != 0) && (strcmp(input[pToken], "write") != 0) && (kind[pToken] != 10)){nextToken();}}N();if (strcmp(input[pToken], "else") == 0){nextToken();}else{error(NO_SIGN_ERR,"else");if ((strcmp(input[pToken], "integer") != 0) && (strcmp(input[pToken], "read") != 0) && (strcmp(input[pToken], "write") != 0) && (kind[pToken] != 10)){nextToken();}}N();}void X(){R();Y();R();}void Y(){if (strcmp(input[pToken], "<") == 0 || strcmp(input[pToken], "<=") == 0 ||strcmp(input[pToken], ">") == 0 || strcmp(input[pToken], ">=") == 0 || strcmp(input[pToken], "=") == 0 || strcmp(input[pToken], "<>") == 0){nextToken();}else{error(NO_SIGN_ERR, "关系运算符");if ((kind[pToken] != 10) && (kind[pToken] != 11)){nextToken();}}}void Z(){if (!isProExisted(input[pToken])){error(SIGN_UNDEFINED_ERR, NULL);}G();if (strcmp(input[pToken], "(") == 0){nextToken();}else{error(NO_SIGN_ERR, "(");if ((kind[pToken] != 10) && (kind[pToken] != 11)){nextToken();}}R();if (strcmp(input[pToken], ")") == 0){nextToken();}else{error(NO_SIGN_ERR, ")");if ((strcmp(input[pToken], "-") != 0) && (strcmp(input[pToken], "*") != 0) && (strcmp(input[pToken], ";") != 0) && (strcmp(input[pToken], "end"))){nextToken();}}}。
西电软院编译原理试题
Xidian University Li Huan编译原理题目解诗云:太初有道,道曰全真。
全真七子,星聚软院1。
重阳归天2,分道七篇。
各执一篇,授业终南。
当是时也,正乃王道长献青真人讲道西电,秘授编译原理心法一篇,以飨众生。
无量寿佛!今晚 Li Huan1此处作者指的是目前西电软件学院七位有德道长:总掌教大护法武道长、首席副掌教顾道长、刘道长讳西洋、沈道长讳沛意、王道长讳献青、高道长讳海昌、陈道婆讳静玉。
此乃huan说,另有其他版本。
不再赘述。
2此处指软件学院开山祖师陈真人讳平。
归天意本离世,此处特指升仙为四大护校法尊之一。
1、填空题(30 分)1.1 以阶段划分的编译器中,语法分析阶段以记号流为输入,语义分析阶段以语法树为输入。
1.2 有正规式 P=a|b 和 Q=cd 则 L(QP)={cda,cdb} ,L((P|Q)Q)={acd,bcd,cdcd} 。
1.3 有两个因素使得有限自动机是不确定的,一个是具有ε 状态转移,另一个是对同一字符,可能有多于一个的下一状态转移。
1.4 词法分析器有四个作用,请给出其中的任意两个:识别记号并交给语法分析器/滤掉源程序中的无用成分/处理与具体平台有关的输入/调用符号表管理器或出错管理器。
1.5 一个定义正确的上下文无关文法,非终结符集合和终结符集合的交集为空,所有出现在产生式左部的文法符号均是非终结符,仅出现在产生式右部的文法符号均是终结符。
1.6 编译源程序的过程中,发现函数定义末尾缺少花括号,该情况是语法错误;发现除数为 0,该情况是语义错误。
1.7 推导 S=>?H=>?FTP =>?FTc=>?Fbc=>?abc 是最右/规范推导。
1.8 产生式 F→A*F|A 提取左因子的结果为 F->AF' F'->*F|ε 。
1.9 对于算术表达式 “a*b+c”,当采用预测分析方法时,接受格局中的“当前剩余输入”应该为空,初始格局中的“当前剩余输入”应该是 a*b+c 。
电子科技大学《程序设计语言与编译》自测题答案
B→.a
B→.b
2. 构造 SLR 分析表;(8 分)
action
goto
a
b
c
d
$
S
A
B
0
S2
1
1
acc
2
S5
S6
3
4
3
S7
R1
4
R3
R3
5
R4
R4
6
R5
R5
7
S5
S6
8
8
R2
R2
3. 该文法是 SLR(1)文法吗?理由是什么?(4 分)
是,不存在多重入口
七、 语义分析题(10 分)
将下面语句翻译成四元式序列:
对使用这个新类型的程序单元来说,新类型的表示是隐蔽的
2. 一个典型的编译程序有哪几部分?
词法分析器、语法分析器、语义分析器、中间代码生成器、优化器、代码生成器
3. 循环优化有哪些措施?
代码外提 强度削弱 删除归纳变量
4. 参数传递有哪几种方式?
5 种:传值 传地址 得结果 传值得结果
四、 推导题(共 10 分)
10.一个对象与其某种属性建立某种联系的过程,称为( D )。
A. 赋值,B.存储,C.定义,D.绑定
二、 多项选择题(每小题 2 分,共 10 分)
1.类型转换的方法( B E )
A. 动态转换,B.拓展,C.静态转换,D.收缩,E.显式转换
2.语句级控制结构有( BCE )
A.递归,B.顺序,C.选择,D.过程调用,E.重复
(109)
(104)(:=,’0’,-,y)
(105)(j,-,-,100)
程序设计语言与编译二
西安电子科技大学《编译原理》.ppt
5)均是句型。句型是一个相当广泛的概念,根据定义3.3可知,α1
和α6同样也是句型。
11
3.2.3 推导、分析树与语法树
对于推导:E => -E => -(E) => -(E+E) => -(id+E) => -(id+id) 它产生句子的方式很不直观,看起来十分困难。
分析树是推导的图形表示,它的表示很直观,并且同时反映语
A→α,其中A∈N(左部),α∈(N∪T)*(右部), 若α=ε,则称A→ε为空产生式(也可以记为A →); (4) S是非终结符,称为文法的开始符号(Start symbol)。■
例3.2 简单算术表达式的上下文无关文法可表示如下:
N={E} T={+,*,(,),-,id} S=E
P: E → E + E
① 语法规则:上下文无关文法(子集-LL文法或LR文法) ② 语法分析:下推自动机(LL或LR分析器),自上而下和自下而 上分析 本章主要内容: <1> 与语法分析有关的基本概念和相关问题 <2> 上下文无关文法 <3> 自上而下分析 <4> 自下而上分析 <5> 上机作业-第二部分:函数绘图语言的语法分析器
分析树既反映了产生句型的推导过程,又反映了句型的结构。
13
3.2.3 推导、分析树与语法树(续2) 更多的情况下,仅关注句型结构,而忽略推导过程。
定义3.6 对CFG G的句型,表达式的语法树被定义为具有下述性质的
一棵树:
(1) 根与内部节点由表达式中的操作符标记;
(2) 叶子由表达式中的操作数标记;
1
3.1 语法分析的若干问题
电子科技大学-计算机学院-编译原理实验-词法分析
#include<stdio.h>#include<string.h>#include<Windows.h>#define MAX_COUNT 1024#define ILLEGAL_CHAR_ERR 1#define UNKNOWN_OPERATOR_ERR 2/*从标准输入读入第一个非空白字符(换行符除外)*/char getnbc(){char ch;ch = getchar();while (1){if (ch == '\r' || ch == '\t' || ch == ' '){ch = getchar();}else{break;}}return ch;}/*判断character是否为字母*/bool letter(char character){if ((character >= 'a'&&character <= 'z') || (character >= 'A'&&character <= 'Z')) return true;elsereturn false;}/*判断character是否为数字*/bool digit(char character){if (character >= '0'&&character <= '9')return true;elsereturn false;}/*回退字符*/void retract(char& character){ungetc(character, stdin);character = NULL;}/*返回保留字的对应种别*/int reserve(char* token){if (strcmp(token, "begin") == 0)return 1;else if (strcmp(token, "end") == 0)return 2;else if (strcmp(token, "integer") == 0)return 3;else if (strcmp(token, "if") == 0)return 4;else if (strcmp(token, "then") == 0)return 5;else if (strcmp(token, "else") == 0)return 6;else if (strcmp(token, "function") == 0) return 7;else if (strcmp(token, "read") == 0)return 8;else if (strcmp(token, "write") == 0)return 9;elsereturn 0;}/*返回标识符的对应种别*/int symbol(){return 10;}/*返回常数的对应种别*/int constant(){return 11;}/*按照格式输出单词符号和种别*/void output(const char* token, int kindNum){printf("%16s %2d\n", token, kindNum);}/*根据行号和错误码输出错误*/bool error(int lineNum, int errNum){char* errInfo;switch (errNum){case ILLEGAL_CHAR_ERR:errInfo = "出现字母表以外的非法字符";break;case UNKNOWN_OPERATOR_ERR:errInfo = "出现未知运算符";break;default:errInfo = "未知错误";}if (fprintf(stderr, "***LINE:%d %s\n", lineNum, errInfo) >= 0) return true;elsereturn false;}/*词法分析函数,每调用一次识别一个符号*/bool LexAnalyze(){static int lineNum = 1;char character;char token[17] = "";character = getnbc();switch (character){case'\n':output("EOLN", 24);lineNum++;break;case EOF:output("EOF", 25);return false;//false表示已读到文件末尾case'a':case'b':case'c':case'd':case'e':case'f':case'g':case'h':case'i':case'j':case'k':case'l':case'm':case'n':case'o':case'p':case'q':case'r':case's':case't':case'u':case'v':case'w':case'x':case'y':case'z':case'A':case'B':case'C':case'D':case'E':case'F':case'G':case'H':case'I':case'J':case'K':case'L':case'M':case'N':case'P':case'Q':case'R':case'S':case'T':case'U':case'V':case'W':case'X':case'Y':case'Z':while (letter(character) || digit(character)){char s[2] = { character };strcat(token, s);character = getchar();}retract(character);int num;num = reserve(token);if (num != 0)output(token, num);else{int val;val = symbol();output(token, val);}break;case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':while (digit(character)){char s[2] = { character };strcat(token, s);character = getchar();}retract(character);int val;val = constant();output(token, val);break;case'=':output("=", 12);break;case'<':character = getchar();if (character == '>')output("<>", 13);else if (character == '=')output("<=", 14);else{retract(character);output("<", 15);}break;case'>':character = getchar();if (character == '=')output(">=", 16);else{retract(character);output(">", 17);}break;case'-':output("-", 18);break;case'*':output("*", 19);break;case':':character = getchar();if (character == '=')output(":=", 20);elseerror(lineNum, 2);//输出“未知运算符”错误break;case'(':output("(", 21);break;case')':output(")", 22);break;case';':output(";", 23);break;default:error(lineNum, 1);//输出"出现字母表以外的非法字符"错误}return true;}/*获得路径*/void getPath(char* in, char* out){char* name;name = strrchr(in, '\\');if (name != NULL)strncpy(out, in, strlen(in) - strlen(name) + 1);elsestrcpy(out, "");}/*获得文件名,不包括扩展*/void getFilename(char* in, char* out){char* fullName;char* extension;fullName = strrchr(in, '\\');extension = strrchr(in, '.');if (fullName != NULL)strncpy(out, fullName + 1, strlen(fullName) - 1 - strlen(extension));elsestrncpy(out, in, strlen(in) - strlen(extension));}/*初始化函数,接收输入文件地址,并打开输入、输出、错误文件、将标准输入重定向到输入文件,将标准输出重定向到输出文件,标准错误重定向到错误文件*/bool init(int argc, char* argv[]){if (argc != 2){return false;}else{char* inFilename = argv[1];//argv[1];char outFilename[MAX_COUNT] = "";char errFilename[MAX_COUNT] = "";char filename[MAX_COUNT] = "";char path[MAX_COUNT] = "";//获得文件名(不包括扩展名)和路径getFilename(inFilename, filename);getPath(inFilename, path);//生成输出文件全部路径strcat(outFilename, path);//strcat(outFilename, "\\");strcat(outFilename, filename);strcat(outFilename, ".dyd");//生成错误文件全部路径strcat(errFilename, path);//strcat(errFilename, "\\");strcat(errFilename, filename);strcat(errFilename, ".err");if (freopen(inFilename, "r", stdin) != NULL&&freopen(outFilename, "w", stdout) !=NULL&&freopen(errFilename, "w", stderr) != NULL)return true;elsereturn false;}}void main(int argc,char* argv[])//argv[1]是输入文件地址{if (init(argc,argv)){while (LexAnalyze()){}}fclose(stdin);fclose(stdout);fclose(stderr);return;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第二章 词法分析——单词
[例2.1]语句 position := initial + rate * 60 记号 id ks id ks id ks number 问题:一个单词究竟是标识符、关键字、字面量还是特殊 符号? 根据构词规则来产生和识别
将产生和识别单词的规则称为模式,按照某个模式识别 出的元素称为记号(token),而单词指被识别出元素自身 的值。
言,正则表达式
[例2.3]字母表∑={a, b, c} 字符串: ε, a, b, c, aa, ab, ac, ba, bb, bc,… ∑上所有字符串构成的语言L: L={ε, a, b, c, aa, ab, ac, ba, bb, bc, ...} ∑上所有字符串(模式非形式化的表达) 形式化的表达: ∑* (正则表达式) 正则表达式表达的语言L(∑*)= {ε, a, b, c, aa, ab, ac, ba, bb, bc, ...} 11
主要内容
词法分析中的若干问题 模式的形式化描述 记号的识别 从正规式到词法分析器
4
第二章 词法分析——单词
单词(组成程序的元素)
public class TestOfDeclared { public static void main(String[] args) { try{ ListOfNumbersDeclared list = new ListOfNumbersDeclared(); list.writeList(); }catch(Exception e){}; System.out.println("A list of numbers is created and stored in OutFile.txt"); } }
单词举例
const
模式的非形式化描述
const
if(03)
relation(81) id(82) num(83) literal(84)
if
<, <=, =, <>, >, >= pi, count, D2 3.1416, 0, 6.02E23 “core dumped”
<, <=, =, <>, >, >= 字母打头的字母数字串 任何数值常数 双引号间的任意字符串
Comment
{x is an integer}
括号间的任意字符串
8
第二章 词法分析——记号
记号 记号是按照某个模式识别出的元素。 赋值句position := initial + rate * 60 position、initial和rate均为标识符,种类均是id。
问题:当识别出一个id时,如何判定是哪个id ? 当识别出一个relation时,究竟是 = 还是 < ?
5
第二章 词法分析——单词
单词的基本分类: 关键字(保留字), kw (key word, or reserved word) 在程序设计语言中有着固定的意义 while, if, else, for, class 不允许用它们再表示其它的意思 标识符 id (identifier) 程序设计语言中最大的一个类别 为实体起个名字,便于之后的称呼和使用 可以用标识符命名的实体包括:类型名、变量名、过程名、常量名、类 名、对象名、程序包名等 字面量 literal,num 直接以其字面所表示的常量 25,true,“This is an apple” 注意:字面量和常量的区别(常量可以是字面量,也可以是常量名,pi) 特殊符号 ks (key symbol, or special symbol) 类似于自然语言中的标点符号,每个符号都有各自的特殊用途 6 +,-,*等
第二章 词法分析——正则表达式
字符串:字母表上的字符构成的串 相关术语 示例
长度:|S| ε 连接:S1S2 多次连接:Sn S的前缀X S的后缀X S的子串X S的真前缀 S的真后缀 S的真子串 S的子序列X |abc| = 3 |ε| = 0 abc def = abcdef (abc)3 = abcabcabc abc的前缀有:ε,a,ab, abc abc的后缀有:ε,c,bc, abc abc的子串有: ε,a,b, c, … abc的真前缀有:a,ab ? ? abdf是abcdef的一个子序列
12
第二章 词法分析——正则表达式
字符串的集合 及其运算 Φ 空集合 意义
{ε}
X=L∪M X=L∩M
空串是唯一元素
并: X={s| s∈L or s∈M } 交: X={s|s∈L and s∈M}
X=LM
X=L* X=L+
连接: X={st|s∈L and t∈M }
(星)闭包: X=L0∪L1∪L2∪... 正闭包: X=L1∪L2∪L3∪...
7
第二章 词法分析——单词
三个术语:
模式(pattern):产生和识别元素的规则 记号(token): 按照某个模式(或规则)识别出的元素(一组) (记号的类别可以用整型编码表示,例01表示const) 单词(lexeme):被识别出的元素自身的值(一个),也称为词值
记号的类别
const(01)
id, 1 = id, 2 + id, 3 60 记号流 词法分析:扫描构成源程序的字符流,按词法 规则把它们组成记号流
2
第二章 词法分析——简介
词法分析器的作用与工作方式 词法分析器是编译器中唯一与源程序打交道的部分。 滤掉源程序中的无用成分,如注释、空格、回车等; 处理与平台有关的输入,如文件结束符的不同表示等; 识别记号,并交给语法分析器; 调用符号表管理器或出错处理器,进行相关处理 。 工作方式: (1)单独扫描,(2)作为语法分析器的子程序,(3)并行 工作
源程序 词法分析器
源程序
记号流
词法分析器 调用 返回记号 语法树
记号流 源程序 词法分析器 语法分析器
语法分析器
语法树
3
第二章 词法分析——简介
x := y + z * 60.0 ; <id,1> := <id,2> + <id,3> * <60.0> ; 字符流到记号流
两个概念:
词法规则(构词规则):规定单词形成的规则 相当于立法,规定语言所允许的合法单词 词法分析:根据词法规则识别输入序列 相当于执法,识别出合法的单词、指出非法的输入序列
若 L = {a, b}, M = {c, d},则 LM = {ac, bc, ad, bd},L∩M = Φ L* = {ε, a, b, aa, bb, ab, ba, aaa, ...} L+ = { a, b, aa, bb, ab, ba, aaa, ...} 13
记号=记号的类别+记号的属性 [例2.2]表达式
类别 属性 注意:5?
mycount
>
25 由三个记号组成
83 25
记号的类别
relation(81) id(82) num(83)
9
82 81 “mycount” 5
第二章 词法分析——模式
正规式 正则表达式
Regular Expression
记号的类别 const(01) if(03) relation(81) id(82) 单词举例 const if <, <=, =, <>, >, >= pi, count, D2 模式的非形式化描述 const if <, <=, =, <>, >, >= 字母打头的字母数字串
num(83)
literal(84) Comment
3.1416, 0, 6.02E23
“core dumped” {x is an integer}
任何数值常数
双引号间的任意字符串 括号间的任意字符串
10
第二章 词法分析——正则表达式
编译原理课所涉及到的第一个形式化的概念 正则表达式涉及到的概念有:字母表、字符串、语
第一章内容回顾
源程序 词法分析
语言与语言的翻译 编译器的基本组成 编译器的分析/综合模 式(编译器基础架构) 扫描遍数 编译器的编写
语法分析 符 号 表 管 理 语义分析 中间代码生成 代码优化 目标代码生成 目标代码
出 错 处 理
1
第二章 词法分析——简介
C语言赋值语句: 字符流 符 号 表 position = initial + rate 60 1 position . . . ... 2 initial 词法分析器 3 rate ...