编译原理-词法分析
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(1)文法描述及其LL(1)分析表 表达式语言(XL)的语法规则如下: 1. 程序 → 表达式; 2. |表达式;程序 3. 表达式→ 表达式 + 项 4. |项 5. 项 → 项 * 因式 6. |因式 7. 因式 → num_or_id 8. |(表达式) 将该语言的文法转换为如下的LL(1)文法: 1 prgm → expr;prgm’ → factor term’ 2 prgm’ → prgm → *factor term’ 3 prgm’ →ε 10 →ε 4 expr → term expr’ → (expr) 5 expr →ε 12 num 6 expr’ → +term expr’ → prgm 7 expr’ →ε 该LL(1)文法的LL(1)分析表如下: T N prgm prgm’ expr expr’ term term’ 8 10 9 Num 1 2 4 6 8 + * ( 1 2 4
《编译原理》实验
《编译原理》是国内外各高等院校计算机科学技术类专业,特别是 计算机软件专业的一门重要专业课程。该课程系统地向学生介绍编译程 序的结构、工作流程及编译程序各组成部分的设计原理和实现技术。由 于该课程理论性和实践性都比较强,内容较为抽象复杂,涉及到大量的 软件设计算法,因此,一直是一门比较难学的课程。为了使学生更好地 理解和掌握编译技术的基本概念、基本原理和实现方法,实践环节非常 重要,只有通过上机进行程序设计,才能使学生对比较抽象的教学内容 产生具体的感性认识,增强学生综合分析问题、解决问题的能力,并对 提高学生软件设计水平大有益处。 本实验内容可在《编译原理》课程教学的同时,安排学生进行相关 的实验。实验平台可选择在MS-DOS或Windows操作系统环境,使用 C/C++的任何版本作为开发工具。学生在做完试验后,应认真撰写实验 报告,内容应包括实验名称、实验目的、实验要求、实验内容、测试或 运行结果等。
ε_Closure
{0,2,4,6,12} {0,1,3,4,5,7,13,14,18,19} {8,9} {15} {9,10,11,13,14,18,19} {15,16,17,19}
Move(’.’) NFA DFA 1 1 4 5 4 5 NFA Φ {8} Φ Φ Φ Φ
0 1 2 3 4 5
实验二 NFA的确定化
1.实验目的
设计并实现将NFA确定化为DFA的子集构造算法,从而更好地理解 有限自动机之间的等价性,掌握词法分析器自动产生器的构造技术。该 算法也是构造LR分析器的基础。 2.实验要求 设计并实现计算状态集合I的ε闭包的算法ε_Closure(I)和转换函 数Move(I,a),并在此基础上实现子集构造算法Subset_Construction。 利用该从NFA到DFA的转换程序Subset_Construction,任意输入一个NFA N=(S,Σ,δ,s0,F),输出一个接收同一语言的DFA M=(S’,Σ,δ’,s0’,F’)。 3.实验内容 (1) 令I是NFA N的状态集S的一个子集,I的ε闭包的 ε_Closure(I)构造规则如下: (a) 若s∈I,则s∈ε_Closure(I); (b) 若s∈ε_Closure(I)且δ(s, ε)=s’而s’ ∉ε_Closure(I) ,则s’∈ε_Closure(I) 根据上面的规则,下面给出了一个计算I的ε闭包的算法 ε_Closure(I)。 SET S; SETε_Closure(input) SET *input; { S=input; /* 初始化 */ push(); /* 把输入状态集中的全部状态压入栈中 */ while(栈非空){ Nfa_state i; pop(); /* 把栈顶元素弹出并送入i */ if(存在δ(i, ε)=j) if(j不在S中) { 把i加到S中; 把j压入栈中; } } return S; /* 返回ε_Closure(input)集合 */ } 完成上述算法的设计。 (2) 令I是NFA N的状态集S的一个子集,a∈Σ, 转换函数 Move(I,a)定义为:
char if else for while 标识符ID 整型常数NUM = + * / ( )
3 4 5 6 7 10 20 21 22 23 24 25 26
{ } , : ; > < >= <= == != & &&
30 31 32 33 34 35 36 37 38 39 40 41 42
char *KEY_WORDS[7]={″main″,″int″,″char″,″if″, ″else″,″for″,″while″}; 用以存放单词符号二元式的数据结构可如下定义: #define MAXLENGTH 255 /* 一行允许的字符个数 */ union WORDCONTENT { /* 存放单词符号的内容 */ char T1[MAXLENGTH];/* 存放标识符及由两个(以上)字 符组成的符号 */ int T2; /* 存放整型常数的拼数 */ char T3; /* 存放其他符号 */ }; typedef struct WORD { /* 单词符号二元式 */ int code; /* 存放种别编码 */ union WORDCONTENT value; } WORD; 3 按照编译程序一遍扫描的要求,把词法分析器Scaner作为一个 独立的子程序来设计,通过对Scaner的反复调用识别出所有的 单词符号; 4 当Scaner识别出一个单词符号时,则将该单词符号的二元式写 入到输出文件中。若Scaner无法识别出一个单词符号时,则调 用错误处理程序PrintError,显示当前扫描到的字符及其所在 行、列位置,并跳过该字符重新开始识别单词符号。 (4) 测试该设计词法分析器,可对下面的源程序进行词法分析:输出如 下二元式代码序列: 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,})
ε ε eε
D
ε ε ε
18 14 15 16 17 19
NFA N的初态为12,DFA M的初态为ε_Closure({12})。
整个转换过程可用下表来概括。
DFA 状 态 NFA 状态 Move(’D’)
终
Move(’e’) 态 DFA 2 NFA Φ {15} Φ Φ {15} Φ DFA 3 3 否 是 否 否 是 是
(#为输入结束标 志)
Expr 258 非终结符 expr’ 260 term 259 term’ 262 factor 261 prgm 256 prgm’ 257 system_goal 263 (2)文法及其LL(1)分析表的数据结构 文法的产生式可用数组Yy_pushtab[]存放。数组的第一个下标 是产生式号,第一个产生式的序号为0;每列按逆序存放该产生式 右部各符号的常数值,并以0结束。对于该表达式语言XL的LL(1)分 析表,可用数组Yy_d[]存放。第一个下标是非终结符数值,第二个 下标是终结符数值,数组元素的值为:0(表示接受),1(表示产 生式号),-1(表示语法错)。 数组Yy_pushtab[]的具体内容及表示如下:
{12} {1,5} {8} {15} {10} {16}
{1,5} {1,5} {10} {16} {10} {16}
DFA M的状态转换图如下。
D D D D
.
0 e e D D 1 2 4
3
5
实验三 非递归预测分析
1.实验目的 设计一个非递归预测分析器,实现对表达式语言的分析,理解自上 而下语法分析方法的基本思想,掌握设计非递归预测分析器的基本方 法。 2.实验要求 建立文法及其LL(1)分析表表示的数据结构,设计并实现相应的预测 分析器,对源程序经词法分析后生成的二元式代码流进行预测分析,如 果输入串是文法定义的句子则输出“是”,否则输出“否”。 3.实验内容
27 || 43 (2) 关键字main int char if else for while都是小写并都是保留字。 算符和界符 = + - * / & < <= > >= == != && || , : ; { } [ ]
() ID和NUM的正规定义式为: ID→letter(letter | didit)* NUM→digit digit* letter→a | … | z | A | … | Z digit→ 0 | … | 9 如果关键字、标识符和常数之间没有确定的算符或界符作间隔, 则至少用一个空格作间隔。空格由空白、制表符和换行符组成。 (3) 设计词法分析器的步骤: 1 首先根据上面单词符号表及ID和NUM的正规定义式,构造出 状态转换图; 2 定义相关的变量和数据结构。关键字作为特殊标识符处理, 把它们预先安排在一张表格中(称为关键字表),当扫描程 序识别出标识符时,查关键字表。如能查到匹配的单词,则 该单词为关键字,否则为一般标识符。关键字表为一个字符 串数组,其描述如下:
} } 此算法的输出M主要由Trans矩阵描述,其中省略了每个状态是否 为终态的描述,应加以完善。 (4) 测试用例 对下图所示的NFA N用子集构造算法Subset_Construction确定 化。 ε ε ε ε
D
ε
2 0 1 3 13
ε
12
ε ε ε ε
D
.
D
ε ε ε ε
6 4 5 7 8 9 10 11
8 9
term term’
wk.baidu.com
term’ 11 factor →
f actor
13 system_goal
)
; 1 2
# 3
5 7 10
5 7 10
factor
12
11
system_goal 13 13 13 对文法中每个文法符号指定一个常数值,符号编码表如下: 文法符号 常数值 备注 ( Num + ) ; * # 4 6 2 5 1 3 0 终结符
Move(I,a)= ε_Closure(J) 其中,J={s’|s∈I且δ(s,a)=s’} 转换函数Move(I,a)的设计通过调用ε_Closure(input)实现,完 成该函数的设计。 (3) 从NFA N构造一个与其等价的DFA M的子集构造算法,就是要 为DFA M构造状态转换表Trans,表中的每个状态是NFA N状态 的集合,DFA M将“并行”地模拟NFA N面对输入符号串所有 可能的移动。下面给出了子集构造算法Subset_Construction 的框架,请完成其设计过程。 有关数据结构: States[] 是一个M的数组,每个状态有两个域,set域存放N的状态集合, flg域为一标识。 Trans[] 是M的转移矩阵(输入字母表Σ元素个数×最大状态数), Trans[i][a]=下一状态。 i M的当前状态号 a 输入符号,a∈Σ Nstates[] M的下一新状态号 S 定义M的一个状态的N的状态集 初始化: States[0].set=ε_Closure({N的初态}) States[0].flg=FALSE Nstates=1 S=Ф Trans初始化为无状态’-’ while(States[i]的flg为FALSE){ States[i].flg=TRUE; for(每个输入符号a∈Σ){ S=ε_Closure(Move(States[i].set,a)); if(S非空) if(States中没有set域等于 S的状态){ States[Nstates].set=S; States[Nstates].flg=FALSE; Trans[i][a]= Nstates++; } else Trans[i][a]= States中一个set域为S的下标;
实验一 词法分析
2.实验要求 利用该词法分析器完成对源程序字符串的词法分析。输出形式是源 程序的单词符号二元式的代码,并保存到文件中。 1. 实验目的 对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用 状态转换图设计词法分析器的基本方法。 3.实验内容 (1) 假设该语言中的单词符号及种别编码如下表所示。 单词符号及种别编码 单词符号 种别编码 单词符号 种别编码 main int 1 2 [ ] 28 29