西安电子科技大学编译原理 (10)

合集下载

电子科技大学编译原理--A2答案--网络教育

电子科技大学编译原理--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___。

电子科技大学编译原理--B答案--网络教育

电子科技大学编译原理--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___。

编译原理

编译原理

习惯称法 汇编语言-机器指令:汇编(或交叉汇编) 程序设计语言-汇编语言或机器指令:编译(或解释) 高级语言之间:转换(或预编译) 逆向:反汇编、反编译
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 从面向机器的语言到面向人类的语言

西安电子科技大学计算机科学与技术系本科培养方案

西安电子科技大学计算机科学与技术系本科培养方案

计算机科学与技术专业本专业是计算机硬件与软件相结合、面向系统、侧重应用的宽口径专业。

通过基础教学与专业训练,培养基础知识扎实、知识面宽、工程实践能力强,具有开拓创新意识,在计算机科学与技术领域从事科学研究、教育、开发和应用的高级人才。

本专业开设的主要课程有:电子技术、离散数学、程序设计、数据结构、操作系统、计算机组成原理、微机系统、计算机系统结构、编译原理、计算机网络、数据库系统、软件工程、人工智能、计算机图形学、数字图像处理、计算机通讯原理、多媒体信息处理技术、数字信号处理、计算机控制、网络计算、算法设计与分析、信息安全、应用密码学基础、信息对抗、移动计算、数论与有限域基础、人机界面设计、面向对象程序设计等。

计算机科学与技术专业从三年级开始,设有计算机软件、计算机应用、计算机安全技术三个方向,分别供不同兴趣的同学根据自身发展方向自由选择!本专业毕业生应获得以下几个方面的知识和能力:1.掌握电子技术和计算机组成与体系结构的基本原理、分析方法和实验技能,能从事计算机硬件系统开发与设计。

2.掌握程序设计语言、算法与数据结构、操作系统以及软件设计方法和工程的基本理论、基本知识与基本技能,具有较强的程序设计能力,能从事系统软件和大型应用软件的开发与研制。

3.掌握并行处理、分布式系统、网络与通信、多媒体信息处理、计算机安全、图形图象处理以及计算机辅助设计等方面的基本理论、分析方法和工程实践技能,具有计算机应用和开发的能力。

4.掌握计算机科学的基本理论,具有从事计算机科学研究的坚实基础。

计算机科学与技术专业培养方案一、培养目标及模式本专业培养德、智、体、美全面发展,具备自然科学基础知识,系统地掌握计算机科学理论、计算机软硬件系统及应用知识和技能的高级人才。

毕业生基本具备本领域分析问题和解决问题的能力,具备良好外语运用能力。

本专业培养模式分为“研究开发型”和“工程应用型”两种,分别对应“计算机科学”和“计算机工程”两个方向,各方向对应的培养目标是:●“计算机科学”方向:具有扎实、深入的高等数理基础和专业理论基础;外语水平高,听说读写能力强;具有较强的知识更新能力、创新能力、综合设计能力和工程化能力;具有一定的学科前沿知识和从事科学研究的能力。

编译原理 答案

编译原理 答案

Ia {1,2} {1,2} {1,2}
Ib {1,2,Y} {1,2,Y} Nhomakorabea{1,2,Y} 重新命名
S 1 2 3
a 2 2 2
b 3 3 3
图2-18 图2-17确定化后的状态转换矩阵

比较图2-18与图2-15,重新命名 后的转换矩阵是完全一样的,也即正规 式 (a|b)*b 可以同样得到化简后的 DFA 如 图 2-16 所示。因此,两个自动机完全一 样,即两个正规文法等价。 (2) 对图2-16,令A对应状态1, B对应状态2,则相应的正规文法G[A]为 B→aA|bB|b G[A] 可 进 一 步 化 简 为 G[S] :
2
a X 1
b a Y
图2-5 正规式(ab)*a对应的NFA
2
b X a 1
a Y
图2-6 正规式a(ba)*对应的DFA

这两个正规式最终都可得到最简 DFA,如图2-7所示。因此,这两个正规 式等价。
a 0 b 1
图2-7 最简NFA

2.5 设 有 L(G)={a2n+1b2ma2p+1| n≥0,p≥0,m≥1}。 • (1) 给出描述该语言的正规表达 式; • (2) 构造识别该语言的确定有限 自动机(可直接用状态图形式给出)。 • 【解答】 该语言对应的正规表 达 式 为 a(aa)*bb(bb)*a(aa)* , 正 规 表 达 式对应的NFA如图2-8所示。
3
a X 1
a 2 b Y

a
4
b
图2-14 正规式((a|b)*|aa)*b对应的NFA

用子集法将图2-14所示的NFA确 定化为DFA,如图2-15所示。

西安电子科技大学编译原理 (23)

西安电子科技大学编译原理 (23)
• 标识符initial形成的记号是<id,2> • 加号形成的记号是<+> • 标识符rate形成的记号是<id,3> • 乘号*形成的记号是<*> • 60形成的记号是<60>

其他面向特定应用领域的语言 计算机辅助设计:MATLAB 集成电路设计:VHDL、Verilog 虚拟现实与人机交互:VRML ……
21
程序设计语言的发展
计算机语言举例
[例1]通用程序设计语言与汇编语言(包括机器 指令) Pascal语句: x := a+b; C++语句: x = a+b; 汇编指令: 十六进制代码 汇编指令 A10002 MOV AX, [A] 8B1E0202 MOV BX, [B] 01D8 ADD AX, BX A30402 MOV [X], AX 22
输出
特点
编译器:工作效率高,即时间快、省空间;交互性与动 态特性差、可移植性差。被大多数PL的翻译所采用; 解释器:工作效率低,即时间慢、费空间;交互性与动 态特性好、可移植性好。早期的Basic和现在的Java等。 基本功能:二者相同; 采用技术:从翻译的角度来讲,两种方式所涉及的原理、 方法、技术相似。
26
1.3 编译器与解释器
语言翻译的两种基本形态 先翻译后执行
源程序 输入数据
边翻译边执行
源程序 输入数据
编译器 目标程序
目标程序
输出
解释器
输出
[例5]假设有源程序P:x=3;
P 编译器 目标程序 目标程序
P
解释器
x=3
27
3
x=3
3
1.3 编译器与解释器

西电软院编译原理试题By李欢

西电软院编译原理试题By李欢

A B C D DFA:
<3> Move(C,a)=C Move(C,b)=D Move(D,a)=C Move(D,b)=D B、C、D 不可分。合并为一。 DFA A’:
3.2 给定文法 G: B→B & C | C
Xidian University
Li Huan
C→E < E | E E→~E | n 和右句型“B & n < ~n” 。 <1>画出该句型对应的分析树; <2>指出句型中的所有短语、直接短语和句柄。 解: <1>
Li Huan
1.12
假定运算+与*都是左结合的,且运算*比运算+优先级高,则算术表达式 xyuv+*+ 。
x+y*(u+v)的后缀式是 1.13
拉链-回填技术是语法制导翻译过程中使用的一种基本技术,其基本思想
是当三地址码中的转向不确定时 将所有转向同一地址的三地址码拉成一个 链 址 ,而一旦所转向的地址被确定,则 。 为此链上所有的三地址码回填入此地
2.5 给出下图中的树对应的三地址码序列。
Xidian University
Li Huan
解:
2.6
假设数组下标从 0 开始,对于有 5 行 6 列的数组 a[5][6],已知该数组
的存储空间首地址为 a,每个素 a[2][3]的地址。 答:a+(2*6+3)* w =15w+a 3、计算题(50 分) 3.1 给定正规式 R = a(a|b)* <1> 用 Thompson 算法构造识别 L(R)的 NFA N; <2> 用“子集法”把 N 确定化(写出完整过程) ,得到识别 L(R)的 DFA D; <3> 如果 D 不是最简 DFA,请找出最简 DFA D’。 答:<1>笔误:红线一端从 1 开始。

西电编译原理_第二章习题解答

西电编译原理_第二章习题解答
(3) 再考虑:仅由1组成的串,或 若干1打头的串。
最终的正规式: 1* | 1*(01|0)* = 1*(01|0)*
© 西安电子科技大学 · 软件学院
5
1. 根据模式写出正规式
习题2.4 (2) 所有不含有子串 011 的01串 思路2:考虑包含 011 的串,然后构造没有011的串 ① 含有 子串 011 的最简单的串:
然后据上,考查每条从初态到终态的路径,综合正规式即可。
© 西安电子科技大学 · 软件学院 9
2.依据NFA/DFA,给出正规式
习题2.10 (2) 用正规式描述 DFA 所接受的语言;
0 b,c 2 b,c a b a a,c 1
该DFA从初态到终态有三条路径:0b2,0c2,0a1b2 用正规式表示为: b | c | a(a|c)*b, 而且是这三条路径均至少重复一次, 故最终的正规式为:(b|c|a(a|c)*b)+
© 西安电子科技大学 · 软件学院 13
其它
习题2.9 构造 10*1 的最小DFA 解: 活用 Thompson 算法 (1) 分解为三部分:1,0*,1; (2) 画出三者的状态转换图:
0 1 0 1 2 3 1 4
(3) 连接运算:子图首尾相连
0
1
0 1 1
1
4
这已经是最小的DFA
© 西安电子科技大学 · 软件学院
© 西安电子科技大学 · 软件学院
11
其它
关于:正规式 -> NFA -> DFA -> DFA最小化:
说明:(一般)逐步计算 正规式->NFA: (1)呆板Thompson算法: 自上而下分解正规式—— 语法树, 自下而上构造NFA —— 后续遍历; 特点:每个运算对应一次构造,繁琐! (2)活用Thompson算法: 分解正规式:得到若干规模适中的子正规式; 为每个子正规式:画出其最简的状态转换图(子图); 按Thompson算法,将子图组合,得到完整的图。

电子科技大学《计算机编译原理)》20春期末考试.doc

电子科技大学《计算机编译原理)》20春期末考试.doc

1.编译程序的工作情况有三种,分别是解释型、编译型和()。

A.综合型B.并列型C.汇编型D.不确定型【参考答案】: C2.文法中不包含左公共因子是LL(1)文法的()。

A.充分条件B.必要条件C.充要条件D.即不充分也不必要的条件【参考答案】: B3.在规范归约中用来刻画可归约串的是()。

A.短语B.句柄C.最左素短语D.素短语【参考答案】: B4.文法G[S]:S→S+U|U ,U→U*V|V ,V→(S)a 。

则句型P+T+i的句柄和最左素短语为()。

A.V+U和aB.V和V+UC.a和V+U+aD.V和U【参考答案】: B5.中间代码设计原则是()。

A.简洁,占用内存少B.接近自然语言C.可替代编译程序D.容易生成和翻译为目标代码【参考答案】: D6.设有文法G[S]: S→S8|S9|Sa|Sc|a|b|c 下列句子中符合该文法的有()。

①ab9 ②a9c98 ③aaa ④bc89 可选项有:A.①B.②③④C.③④D.①②③④【参考答案】: B7.编译程序工作的后端包含的阶段有()。

A.语义分析、代码优化、代码生成B.词法分析、语法分析、代码生成C.中间代码生成、代码优化、代码生成D.语义分析、中间代码生成、代码优化【参考答案】: C8.一个句型中称为句柄的是该句型的最左()。

A.最左终结符号B.所有短语C.所有句子D.最左直接短语【参考答案】: D9.设文法G[S]:S→SB|B ,B→0|b 则对句子0b0,以下推导为规范推导的是()。

A.SSBSBBBBB0BB0bB0b0B.SSBSBBBBBBB0Bb00b0C.SSBSBBSB0Sb0Bb00b0D.SSBS0SB0Sb0Bb00b0【参考答案】: D10.已知文法G[E]:E→3EXY|34Y,YX→XY,4X→44,4Y→45,5Y→55 该文法是Chomsky文法类型中的()。

A.0型文法B.1型文法C.2型文法D.3型文法【参考答案】: B11.一个LR分析器由三部分组成,分别是总控程序、分析表和()。

电子科技大学-计算机学院-编译原理实验-词法分析

电子科技大学-计算机学院-编译原理实验-词法分析

#include<>#include<>#include<>#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;;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];yd");rr");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;}。

西电编译原理_总复习

西电编译原理_总复习

构造SLR(1)分析表的方法:
a J I A K
1.可移进项直接从DFA上看: action[I,a]:=sj goto[I,A]:=k 2.可归约项分两步走:若在I状态中有[A→α.], 首先计算:FOLLOW(A), 然后填写:action[I,b]:=Ri 其中:b∈FOLLOW(A)且A→α是第i个产生式。Βιβλιοθήκη ,三、计算题(3.3)
3.3(13分)已知一个NFA如图。 (a)(4 分 ) 用自然语言简要叙述该自动机所识别的语 言 的特点,列举两个它可识别的串。 (b)(3分)写出与该自动机等价的正规式r。 (c)(6分)用子集法构造识别r的最小DFA。
a,b 0 b 1 b
a,b 2
三、计算题(3.4)
3.4( 15 分)有文法 G 如下(注: G 中终结符 id 仅由单个英文字母 组成,如a, b等):E→E*T|T T→T+F|F F→(E)|id 和G的语法制导翻译如下:
E→E1*T | T T→T1+F | F F→(E) | id {E.place=newtemp; emit(*,E1.place,T.place,E.place;} {E.place=T.place;} {T.place=newtemp; emit(+,T1.place,F.place,T.place;} {T.place=F.place;} {F.place=E.place;} {F.place=;}
用自然语言给出下述正规式所描述的语言,并构造他们的最小DFA 10*1 (0|1)*011(0|1)*
问题:看得懂,但是不太会用自然语言较好的表达 说明:所谓用自然语言描述就是解释字符串的性质,一般情 况下是已经有了形式化描述。注意:这就是练习的目的。 解: 10*1:首尾是1中间有零或若干个0的01串。 (0|1)*011(0|1)* :至少含一个011的01串。 注意:绝对不允许用正规式形式表示,因为正规式已经给出

西电_编译原理上机报告

西电_编译原理上机报告

编译原理上机报告《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答案--网络教育

《计算机编译原理》试卷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答案--网络教育

《计算机编译原理》试卷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();}}}。

西安电子科技大学《编译原理》.ppt

西安电子科技大学《编译原理》.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 语法分析的若干问题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
FIRST(E)={ (,id, num } FOLLOW(E)={ ),; }
L →E ; L | ε E →TE' E'→ + T E' | - T E' | ε T →FT' T'→*F T'|/FT'|mod FT'|ε F →(E) | id | num
L →E ; L | ε E →TE' E'→ + T E' | - T E' | ε T →FT' T'→*F T'|/FT'|mod FT'|ε F →(E) | id | num
对文法的每个产生式A→α ② 对FIRST(α)的每个终结符a,加入α 到M[A,a]; ③ 若ε∈FIRST(α),则FOLLOW(A)每 个终结符b(包括#),加入α到M[A, b];
/ mod ( E;L TE' ε ε ) ; # ε
+
-
*
E'
T T' F
id
num
(E)
3.4 自上而下语法分析

...
E
T T F F id T FT
T
T FT
6
非终 结符 E E T T
输 入 符 号
id
E TE
+
E +TE

...
T FT T T FT
F
F id





$E
id id + id$
id id + id$ id id + id$ id id + id$ id + id$ id + id$ id + id$ id + id$ F id
11
① ② ③
加#到FOLLOW(S),其中S是开始符号,#是输入结束标记 若有产生式A→αBβ,则除ε外,FIRST(β)的全体加入到FOLLOW(B)。 若有产生式A→αB或A→αBβ且ε∈FIRST(β),则FOLLOW(A)的全体加入到FOLLOW(B)。
3.4 自上而下语法分析
[例3.22] 计算非终结符的FIRST与FOLLOW。L →E ; L | ε
5
3.4 自上而下语法分析
预测分析表的构造 非递归预测分析方法的特征是预测分析器与文法无
关,所有预测分析器的驱动器都是相同的,而唯一 不同的是预测分析表 因此,所谓构造预测分析器,实际上就是构造给定 文法的预测分析表
非终 结符 E 输 入 符 号
id
E TE
+ E +TE
输入缓冲区
(被分析的符号串)
a +b $
栈 (文法符号串)
初始时栈中除 了$以外,只 含有文法的开 始符号
X Y Z $
预测分析程序
输出流
分析表M
分析表是二维数组M[A,a] A为非终结符,a为终结 符或者$
2
3.4 自上而下语法分析
输入缓冲区
(被分析的符号串)
a +b $
栈 (文法符号串)
初始时栈中除 了$以外,只 含有文法的开 始符号
通俗地讲,α的FIRST集合就是从α开始可导出的文法符号序列中的开 头终结符。 而A的FOLLOW集合,就是从开始符号可以导出的所有含A的文法 符号序列中A之后的终结符。
8
例如:
L →E ; L | ε E →TE' E'→ + T E' | - T E' | ε T →FT' T'→*F T'|/FT'|mod FT'|ε F →(E) | id | num
内容回顾
消除二义性 消除左递归 消除左因子 递归下降预测分析(递归下降子程序)

文法,状态迁移关系,EBNF,递归下降子程序
下推自动机*
1
3.4 自上而下语法分析
非递归的预测分析
不采用递归调用 预测分析器的关键是如何选择一个非终结符的产生 式 非递归的预测分析器通过检查分析表来选择产生式 (表驱动的预测分析器)
4
3.
驱动器算法
算法3.4 非递归的预测分析 输入 输入序列ω和文法G的预测分析表M 输出 若ω∈L(G),得到ω的一个最左推导;否则指出一个错误 方法 初始格局为: (#S,ω#,分析器的第一个动作) 令ip指向ω#中的第一个终结符,top指向S; loop x := top^; a := ip^; if x∈T then if x=a then pop(x); next(ip); -- 匹配终结符 else error(1); end if; -- 出错:栈顶终结符不是a else if M[x, a] = X→Y1Y2...Yk then pop(X); push(YkYk-1...Y2Y1); --展开非终结 符 else error(2); endif; -- 出错:产生式不匹配 end if; exit when x = a= #; -- 分析成功 end loop;
FIRST(X1X2...Xn)的计算方法:所有FIRST(Xi) (i=1,2,..,k)的并集,其 中k为第一个具有性质ε不属于FIRST(Xk)的文法符号
X1X2...Xk…Xn
FIRST(X1) FIRST(X2) ... FIRST(X(k-1))
10
3.4 自上而下语法分析
算法3.6 计算所有非终结符的FOLLOW集合 输入 文法G 输出 G中所有非终结符的FOLLOW集合 方法 应用下述规则: ① 加#到FOLLOW(S),其中S是开始符号,#是输入结束标记 ② 若有产生式A→αBβ,则除ε外,FIRST(β)的全体加入到 FOLLOW(B)。 ③ 若有产生式A→αB或A→αBβ且ε∈FIRST(β),则FOLLOW(A) 的全体加入到FOLLOW(B)。 步骤3的理解: 若 S =*>δAa a紧跟A之后 则 =*>δαBa a也紧跟B之后 因为 ε∈FIRST(β) 使得B成为A产生式右部最右的文法符号
id L E E' T T' F id num FT' FT' ε ε *FT' /FT' mod FT' (E) E;L TE' num E;L TE' +TE' -TE' FT' ε ε
15
+
-
*
/
mod
( E;L TE'
)
;
# ε
ε
ε
4.
用预测分析器分析句子
动作 含义 pop(L), push(E;L) (L→E;L) push(TE') (E→TE') pop(T), push(FT') (T→FT') push(id) (F→id) pop(id), next(ip) id pop(T') (T'→ε) pop(E'), push(+TE') (E'→+TE') next(ip) + pop(T), push(FT') (T→FT') push(id) (F→id) pop(id), next(ip) id pop(T'), push(*FT') (T'→*FT') pop(*), next(ip) * push(id) (F→id) pop(id), next(ip) id pop(T') (T'→ε) pop(E') (E'→ε) pop(;), next(ip) ; pop(L) (L→ε) 正确结束
3.4 自上而下语法分析
算法3.7 构造预测分析表 输入 文法G 输出 分析表M 方法 应用下述规则 ① 对文法的每个产生式A→α,执行2和3; ② 对FIRST(α)的每个终结符a,加入A→α到M[A,a]; ③ 若ε∈FIRST(α),则对于FOLLOW(A)每个终结符b(包括#), 把A→α到加入M[A,b](包括M[A,#] ); ④ M中其它没有定义的条目均是error。
9
3.4 自上而下语法分析
算法3.5 计算X的FIRST集合 输入 文法符号X 输出 X的FIRST集合 方法 应用下述规则: ① 若X∈T(终结符),则FIRST(X)={X}; ② 若X是非终结符且有X → ε,则加ε到FIRST(X); ③ 若X是非终结符且有X→Y1Y2...Yk,那么对所有j(1≤j<k),若 a∈FIRST(Yj+1)且ε∈FIRST(Yi), 0ij则加入a到FIRST(X)。
7
预测分析器根据分析表 检测输入id * id + id是否 能有文法表达
$E T $E T F $E T id $E T $E T F $E T F $E T id
E TE T FT F id T FT
3.4 自上而下语法分析
提示:自下而上计算FIRST,自上而下计算FOLLOW
E →TE' FIRST(F) = {( ,id, num} E'→ + T E' | - T E' | ε FIRST(T‘) = {* , / , mod, ε} T →FT' FIRST(T) = FIRST(F) = {( , id, num} T'→*F T'|/FT'|mod FT'|ε F →(E) | id | num FIRST(E‘) = {+ , - ,ε} FIRST(E) = FIRST(T) = FIRST(F) = {( ,id,num} FIRST(L) = {ε}∪FIRST(E) = {ε ,( ,id, num} FOLLOW(L) = {#} FOLLOW(E) = {) ,;} FOLLOW(E‘) = FOLLOW(E)={) ,;} FOLLOW(T) = FIRST(E’)\ ε ∪ FOLLOW(E’)= {+ ,- , ; ,)} FOLLOW(T‘) = FOLLOW(T) ={+ ,- , ;, )} FOLLOW(F) = FIRST(T‘)\ ε ∪ FOLLOW(T‘) ={+, - ,* ,/ , 12 mod ,) ;}
相关文档
最新文档