14、为MicroC扩展for循环,例如允许使用“for (i = 0; i < 100; i = i + 1) sum = sum + i;”。为此,需要修改CLex.fsl和CPar.fsy中的词法分析器和解析器规范。可以通过在stmt类型中定义一个新的语句构造函数Forloop来扩展Absyn.fs中的MicroC抽象语法,并在解释器的exec函数中添加一个合适的情况。但实际上,一般形式的for循环“for (e1; e2; e3) stmt”等价于一个代码块“{ e1; while (e2) { stmt e3; } }”。因此,让解析器中的语义动作{ … }使用stmt类型中现有的Block、While和Expr构造函数来构造抽象语法就足够了。现有三个程序:(i) 编写含arrsum函数的程序,计算数组前n个元素的和;(ii) 编写含squares函数的程序,用i的平方填充数组;(iii) 编写含histogram函数的程序,计算数组中数字的频率。重写这三个程序,使用for循环代替while循环。
要为 MicroC 扩展 for 循环,按以下步骤操作:
- 修改
CLex.fsl和CPar.fsy中的词法分析器和解析器规范,以识别for循环语法。 - 可以选择在
Absyn.fs的stmt类型中定义新的语句构造函数Forloop来扩展抽象语法,并在解释器的exec函数里添加对应情况;
不过推荐不引入特殊抽象语法,利用现有Block、While和Expr构造函数,因为
for (e1; e2; e3) stmt等价于
{ e1; while (e2) { stmt e3; } } - 重写三个程序,用
for循环替换while循环。这三个程序分别是:
- (i) 编写含arrsum函数的程序,计算数组前 n 个元素的和;
- (ii) 编写含squares函数的程序,用 i 的平方填充数组;
- (iii) 编写含histogram函数的程序,计算数组中数字的频率。
15、在 Absyn.fs 文件中扩展微型 C 语言的抽象语法,加入 C、C++、Java 和 C# 中的前置自增和前置自减运算符。定义类型 expr 如下:type expr =… | PreInc of access(表示 C/C++/Java/C# 中的 ++i 或 ++a[e] )| PreDec of access(表示 C/C++/Java/C# 中的 –i 或 –a[e] )。前置自减和前置自增运算符作用于左值,也就是变量和数组元素,更一般地,作用于任何求值为一个位置的表达式。在 Interp.fs 文件中修改微型 C 语言解释器,使其能够处理 PreInc 和 PreDec 这两个新增的运算符。需要修改 eval 函数,并使用存储操作 getSto 和 setSto 来完成相应功能。
- 在
Absyn.fs中扩展抽象语法,加入前置自增和前置自减运算符。 - 在
Interp.fs中修改解释器以处理这两个运算符。 - 具体需要修改
eval函数。 - 使用
getSto和setSto进行存储操作。
16、扩展微型C语言的词法分析器和语法分析器,使其能够接受 ++e 和 –e 表达式,并构建相应的抽象语法。
要解析包含 ++e 和 --e 表达式的微型 C 源程序,需修改词法分析器和解析器。
同时注意,不能简单将 ++e 扩展为赋值表达式 e = e + 1 ,因为这会导致 e 被计算两次, e 本身可能有副作用,如 ++arr[++i] ,所以 e 应只计算一次。
抽象语法定义示例:
type expr =
...
| PreInc of access (* C/C++/Java/C# ++i or ++a[e] *)
| PreDec of access (* C/C++/Java/C# --i or --a[e] *)
17、扩展微型C语言的词法分析器和语法分析器,以接受C/C++/Java/C#风格的条件表达式 e1 ? e2 : e3。条件表达式的抽象语法可以是 Cond(e1, e2, e3),为此你还需要修改 Absyn.fs 文件。
完成扩展可按以下步骤进行:
- 修改词法分析器(micro - C lexer):在词法分析器的规则中添加

最低0.47元/天 解锁文章
985

被折叠的 条评论
为什么被折叠?



