Как сгенерировать байт-код для оператора if-else
Как мне сгенерировать код, соответствующий инструкции байт-кода, ЕСЛИ ТО - 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
Жасмин, дай мне эту ошибку:
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.
Благодарю.
Я не знаю, будут ли полезны файлы байт-кода (. J), сгенерированные Jasmin, но я пишу это.
Если-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
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):
}