如何实现 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语句有点困惑。

如何实现 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