If statement 如何为if-else语句生成字节码

If statement 如何为if-else语句生成字节码,if-statement,antlr,bytecode,jasmin,jvm-bytecode,If Statement,Antlr,Bytecode,Jasmin,Jvm Bytecode,如何使用optional ELSE分支生成与字节码指令IF-THEN-ELSE对应的代码 例如,程序If-else.pas被认为是正确的,而程序If.pas被认为是不正确的,因为它不包含else分支 If-else.pas var a, b : integer; begin a := 3; b := 5; if a > b then print(a) else print(b) end If.pas var a, b :

如何使用optional ELSE分支生成与字节码指令IF-THEN-ELSE对应的代码

例如,程序If-else.pas被认为是正确的,而程序If.pas被认为是不正确的,因为它不包含else分支

If-else.pas

var a, b : integer;
begin
    a := 3;
    b := 5;
    if a > b then 
        print(a)
    else 
        print(b)
end
If.pas

var a, b : integer;
begin
    a := 3;
    b := 5;
    if a > b then 
        print(a)
end
所以Jasmin告诉我这个错误:

输出。j:62:JAS错误:标签:L11未添加到代码中。

输出。j:发现1个错误

我的grammar.g有以下规则:

stmt -> ID := expr
     | print( expr )
     | if( expr ) then ( stmt ) [ else stmt ]?
     | while( expr ) do stmt
     | begin stmt [ ; stmt ]* end
对于if-else语句,我写了以下内容:

'if' 
    {
        int lfalse = code.newLabel(); //Generates a new number for the LABEL
        int lnext = lfalse;
    }
    ( expr )
    {
        if($expr.type != Type.BOOLEAN) //Checking the condition is boolean
            throw new IllegalArgumentException("Type error in '( expr )': expr is not a boolean."); 
        code.emit(Opcode.IFEQ, lfalse); //I create the instruction IFEQ L(lfalse)
    }
    'then' s1 = stmt 
    {   
        lnext = code.newLabel(); //Generates a new number for the LABEL
        code.emit(Opcode.GOTO, lnext); //I create the instruction GOTO L(lnext)
        code.emit(Opcode.LABEL, lfalse); //I create the instruction L(lfalse):
    }
    ( 'else' s2 = stmt 
    {       
        code.emit(Opcode.LABEL, lnext); //I create the instruction L(lnext):
    })?
但在这种情况下,第二个分支不是可选的,而是必须始终存在。 我如何使它成为可选的?我认为有必要打问号(
('else's2=stmt)?
),但没有。 我正在使用ANTLR

谢谢

我不知道Jasmin生成的字节码文件(.J)是否有用,但我编写了它

如果不是的话

    ldc 3
    istore 1
    ldc 5
    istore 0
    iload 1
    iload 0
    if_icmpgt L7
    ldc 0
    goto L8
  L7:
    ldc 1
  L8:
    ifeq L4
    iload 1
    invokestatic Output/printInt(I)V
    goto L11
  L4:
    iload 0
    invokestatic Output/printInt(I)V
  L11:
    return 
如果.j


这里的问题是,您总是生成一个到LNEXT的跳转,但是当没有else子句时,您不会生成标签本身,从而导致无效代码。您需要无条件地生成标签

我不熟悉Antlr,但根据您编写代码的方式,我怀疑这是正确的方法

'if' 
    {
        int lfalse = code.newLabel(); //Generates a new number for the LABEL
        int lnext = lfalse;
    }
    ( expr )
    {
        if($expr.type != Type.BOOLEAN) //Checking the condition is boolean
            throw new IllegalArgumentException("Type error in '( expr )': expr is not a boolean."); 
        code.emit(Opcode.IFEQ, lfalse); //I create the instruction IFEQ L(lfalse)
    }
    'then' s1 = stmt 
    {   
        lnext = code.newLabel(); //Generates a new number for the LABEL
        code.emit(Opcode.GOTO, lnext); //I create the instruction GOTO L(lnext)
        code.emit(Opcode.LABEL, lfalse); //I create the instruction L(lfalse):
    }
    ( 'else' s2 = stmt )?
    {       
        code.emit(Opcode.LABEL, lnext); //I create the instruction L(lnext):
    }
'if' 
    {
        int lfalse = code.newLabel(); //Generates a new number for the LABEL
        int lnext = lfalse;
    }
    ( expr )
    {
        if($expr.type != Type.BOOLEAN) //Checking the condition is boolean
            throw new IllegalArgumentException("Type error in '( expr )': expr is not a boolean."); 
        code.emit(Opcode.IFEQ, lfalse); //I create the instruction IFEQ L(lfalse)
    }
    'then' s1 = stmt 
    {   
        lnext = code.newLabel(); //Generates a new number for the LABEL
        code.emit(Opcode.GOTO, lnext); //I create the instruction GOTO L(lnext)
        code.emit(Opcode.LABEL, lfalse); //I create the instruction L(lfalse):
    }
    ( 'else' s2 = stmt )?
    {       
        code.emit(Opcode.LABEL, lnext); //I create the instruction L(lnext):
    }