как сгенерировать код, соответствующий инструкции байт-кода IF THEN - 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
Если.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