如何使用optioanal ELSE分支生成与字节码指令对应的代码?那么ELSE?
例如,程序If-else.pas被认为是正确的,而程序If.pas被认为是不正确的,因为它不包含ELSE分支。
如果-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给了我这个错误:
Output.j:62:JAS错误:标签:L11尚未添加到代码中。
Output.j:发现1个错误
我的语法.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)是否有用,但是我写了。
如果-else.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
If.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:
return
答案 0 :(得分:1)
这里的问题是您始终生成跳转到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):
}