根据提供的广工编译原理实验报告的信息,我们可以深入解析该实验的主要内容以及涉及的关键知识点。
### 实验背景
本实验报告出自广东工业大学计算机学院的一门课程“编译原理”。该实验的目标是对PL/0语言进行一定的修改和扩充,具体包括增加新的保留字、替换原有的符号以及增强语法结构等方面。通过这一过程,学生可以更加深入地理解编译器的工作原理,尤其是词法分析和语法分析等关键环节。
### 实验内容概览
#### 增加新的保留字和运算符
1. **新增保留字**:`FOR`, `TO`, `DOWNTO`, `+=`, `-=`, `++`, `--`, `RETURN`
- 这些保留字在词法分析阶段被识别,并且需要在编译器的内部数据结构中有所体现。
2. **替换不等号**:将原来的`#`替换为`<>`
- 此替换不仅涉及符号本身的变化,还需要在语法分析过程中做出相应的调整。
#### 增强语法结构
1. **增加条件语句的ELSE子句**
- 在原有基础上增加了ELSE子句,以支持更复杂的逻辑控制流。
- 需要定义新的文法规则,并绘制相应的语法树。
- 定义语义规则,以确保正确的程序执行路径。
### 理论依据与实现方法
#### 文法表示
对于条件语句的扩展,采用扩展巴科斯范式(EBNF)来表示:
```
条件语句 ::= if <条件> then <语句> [else <语句>]
```
其中,方括号内的部分表示可选。
#### 语法树
对于条件语句,可以通过语法树的形式来清晰地表示其结构。假设条件为`E`,然后的语句为`M1`,else后的语句为`M2`,那么语法树可以表示为:
```
S → if E then M1 S1 [else M2 S2]
```
#### 语义规则
为了实现条件语句的逻辑,需要定义一系列的语义规则。例如:
```
S → if E then M1 S1 [else M2 S2]
{ backpatch(E.true_list, M1.quad);
backpatch(E.false_list, M2.quad);
S.next_list := merge(S1.next_list, E.next_list, S2.next_list) }
```
这里,`true_list`和`false_list`分别表示当条件`E`为真或假时的跳转列表,而`next_list`则用于表示后续语句的执行列表。
#### 修改源代码
为了实现上述功能,需要对编译器的源代码进行修改:
1. **扩展SYMBOL枚举**:在原有的基础上,添加了新的保留字和符号,例如:
```c
enum symbol {
nul, ident, number, plus, minus,
times, slash, oddsym, eql, neq,
lss, leq, gtr, geq, lparen,
rparen, comma, semicolon, period, becomes,
beginsym, endsym, ifsym, thensym, whilesym,
writesym, readsym, dosym, callsym, constsym,
varsym, procsym, forsym, tosym, downtosym,
returnsym, elsesym, plusbecomes, minusbecomes,
dplus, dminus,
};
```
2. **修改关键字数量**:更新`norw`宏的值以反映新的关键字数量。
```c
#define norw 18 /* 关键字个数 */
```
3. **初始化函数**:在初始化函数`init()`中添加新的保留字和符号的映射关系。
```c
ssym['+'] = plus;
ssym['-'] = minus;
ssym['*'] = times;
ssym['/'] = slash;
ssym['('] = lparen;
ssym[')'] = rparen;
ssym['='] = eql;
ssym[','] = comma;
ssym['.'] = period;
ssym[';'] = semicolon;
/* 设置保留字名字, 按照字母顺序, 便于折半查找 */
strcpy(&(word[0][0]), "begin");
// ... (其他保留字)
strcpy(&(word[17][0]), "tosym");
```
### 总结
通过对PL/0语言进行上述的修改和扩充,学生不仅能够加深对编译原理的理解,还能够掌握如何在实际编程环境中实现这些概念。整个实验涵盖了词法分析、语法分析以及语义分析等多个方面,这对于学习编译原理是非常有价值的实践过程。