编译原理实践大作业
注:中间代码须为P-Code
-
下面是语言的关键字包括:
int bool if else while write read
,所有的关键字都是保留字,并且必须是小写 -
专用符号:
+ - * / < <= > >= == != = || && ! ; ( ) { } /* */
-
其他标记: 标识符:字母打头,后接字母或数字,识别出的标识符用 ID 标记,区分大小写字母 无符号整数:由数字组成,用 NUM 标记
-
<ID>∷=<letter>|<ID><letter>|<ID><digit> <NUM>∷=<digit>|<NUM><digit> <letter>∷= a|b|…|z|A|B|…|Z <digit>∷=1|2|…|9|0
-
空格由空白、换行符和制表符组成。空格分开 ID、NUM 关键字
-
注释用
/*….*/
括起,可以放在任何空白出现的位置,可以超过一行,注释不能嵌套
1)<program> ∷= <block>
2)<block> ∷= {<decls> <stmts>}
3)<decls> ∷=<decls> <decl> | ε
4)<decl> ∷= int <aid>; | bool <bid>;
5)<aid> ∷= <ID>
6)<bid> ∷= <ID>
7)<stmts> ∷= <stmts> <stmt> | ε
8)<stmt> ∷= <aid> = <aexpr>; | <bid> = <bexpr>; | if (<bexpr>) <stmt>; | if (<bexpr>) <stmt> else <stmt>; | while (<bexpr>) <stmt>; | write <aexpr>; | read <aid>; | <block>
9)<aexpr> ∷= <aterm> + <aterm> | <aterm> - <aterm> | <aterm>
10)<aterm> ∷= <afactor> * <afactor> | <afactor> / <afactor> | <afactor>
11)<afactor> ∷= <aid> | NUM | (<aexpr>)
12)<bexpr> ∷= <bexpr> || <bterm> | <bterm>
13)<bterm> ∷= <bterm> && <bfactor> | <bfactor>
14)<bfactor> ∷= <bid> | true | false | ! <bfactor> | (<bexpr>) | <rel>
15)<rel> ∷= (<aid>|NUM) (< | <= | > | >= | == | !=) <aexpr>
注意:规则2)中的符号“{” 、“}”为终结符号,不是元符号,规则8)、11)、14)中出现的符号“(”和“)”也是终结符号,不是元符号
关于语义有几点说明:
- 变量应该先声明后使用。变量声明如果和上一层{}中的变量重名,认作是最近的{}声明的变量处理
- If 语句存在悬挂 else 二义性,使用“最近嵌套”非二义性规则解决:else 部分作为当前if的一个子结构立即分析
- 符号 / 表示整数除,任何余数都被截去
-
文档、程序、测试用例齐全,并完成所在分组的指定扩展点,成绩为合格(60分)。
-
根据用户界面的友好程度给予加分。满分为10分,必须支持目标代码单步执行时查看数据栈的功能。只支持命令行运行的不给加分。
-
根据分组检查时间的先后给予时间分。共计有8次检查,时间分依次为 8、6、5、4、3、2、1、0 分。
-
对给出的 CX 语法,可以作如下的扩展或修改(但不限于这些)。必须在说明文档中给出扩展点的语法定义。
-
增加运算符 求余运算符 %(2分) 异或运算符 XOR(2分) 判断整数的奇偶 ODD(2分) 自增++,自减--(3分)
-
增加语句,语法参照 C 语言 case 语句(6分) for 语句(6分) break 语句(4分) continue 语句(4分) exit 语句(4分) do…while 语句(2分) repeat…until 语句(2分)
-
增加基本数据类型 可扩充到支持实数数据类型,实现 +、-、*、/ 等运算。可以采用两种方案:一种是整数类型和实数类型等不允许“混合使用”,但存在两种数据类型的转换操作符;另一种是允许“混合使用”,如当运算结果赋给整型变量时候则自动取整。(10分) 还可以增加如字符等数据类型(视实际情况给分)
-
增加常量(const)的定义与使用(4分)
区分变量与常量,可以参考PL/0语言中的实现方法
-
扩充数组功能(10分左右,视实际情况给分)
增加由任何数据类型构造的确定性一维数组,如整型数据数组。允许定义数组、对数组元素赋值、在表达式中引用数组元素等。
-
允许调用 (call) 过程(8分左右,视实际情况给分)
可以参考 PL/0 语言中的实现方法,也可以参考C语言中的实现方法
-
扩充带参数、返回值的过程(15分左右,视实际情况给分)
比较容易实现的一种模式是数值参数(call by value):调用的实际参数是表达式,它在调用时被算出具体的值。形式参数表示过程的局部变量,它在调用时被赋予相应的实际参数值。此外还可以使用地址参数(call by reference)。过程还可以有返回值。
-
增加记录(结构)(10分左右,视实际情况给分)
-
允许并鼓励在编译器的实现当中(部分)使用 Lex 和 Yacc 等自动工具。
-
注意:上面的这些要求有时会相互影响,也可能需要对语法定义作一定的修改。