如何实现 if 和 else 语句?编写语言编译器时
本文关键字:语句 语言 编译器 else 何实现 实现 if | 更新日期: 2023-09-27 17:55:22
我正在使用Joel Pobar编写的示例项目。我从以下方面得到这个:
http://msdn.microsoft.com/en-us/magazine/cc136756.aspx
好的,所以要实现一个简单的打印命令,我需要:
首先在 Ast.cs 中声明类:
// print <expr>
public class Print : Stmt
{
public Expr Expr;
}
其次,我将该方法实现到解析器.cs:
// <stmt> := print <expr>
// <expr> := <string>
// | <int>
// | <arith_expr>
// | <ident>
if (this.tokens[this.index].Equals("Printl"))
{
this.index++;
Print print = new Print();
print.Expr = this.ParseExpr();
result = print;
}
最后,我在 CodeGen.cs 中实现了一个检查:
else if (stmt is Print)
{
// the "print" statement is an alias for System.Console.WriteLine.
// it uses the string case
this.GenExpr(((Print)stmt).Expr, typeof(string));
this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) }));
}
现在,这允许我创建一个解释器并编译一个文件,如果它与语法匹配。此解释器支持变量、循环以及基本打印文本和变量值。但是,我对如何实现if和else语句有点困惑。
MSIL 有条件分支指令。 您必须将条件表达式的结果安排在值堆栈的顶部,然后使用条件分支跳转到其他内容(跳过当时的内容)或不跳转到其他内容。 然后的东西的结束将无条件地分支到其他东西上。
当然,您需要为其他内容的开头和结尾定义和标记标签。 上面的链接涵盖了标签创建。
以下是在 OpCodes 类中找到的条件分支指令:
Beq Field
Beq_S Field
Bge Field
Bge_S Field
Bge_Un Field
Bge_Un_S Field
Bgt Field
Bgt_S Field
Bgt_Un Field
Bgt_Un_S Field
Ble Field
Ble_S Field
Ble_Un Field
Ble_Un_S Field
Blt Field
Blt_S Field
Blt_Un Field
Blt_Un_S Field
Bne_Un Field
Bne_Un_S Field
Brfalse Field
Brfalse_S Field
Brtrue Field
Brtrue_S Field
Switch Field
请注意,其中许多将比较与条件分支相结合。 例如
如果值 1 小于或等于值 2,则
ble
指令将控制权转移到指定的目标指令。其效果与执行cgt
指令(浮点数cgt.un
)相同,后跟特定目标指令的brfalse
分支。
ILGenerator.DefineLabel()
的文档有一个完整的条件实现示例:
IF A < 100 AND B < 100
RETURN A + B
ELSE
RETURN -1