2014-05-23 8 views
0

옵티 오날 ELSE 분기가있는 경우 바이트 코드 명령어에 해당하는 코드를 어떻게 생성합니까?if-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 : 찾을 수 내 문법 · G는이 규칙이

1 오류 :

'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 문에 대한

stmt -> ID := expr 
    | print(expr) 
    | if(expr) then (stmt) [ else stmt ]? 
    | while(expr) do stmt 
    | begin stmt [ ; stmt ]* end 

을 그러나이 방법으로 두 번째 지점은 선택 사항이 아니며 항상 존재해야합니다. 선택 사항을 어떻게 만들 수 있습니까? 나는 물음표 (('else' s2 = stmt)?)가 필요하다고 생각했다. ANTLR을 사용하고 있습니다.

감사합니다.

Jasmin이 생성 한 바이트 코드 파일 (.J)이 유용 할 지 모르지만 필자는이 코드를 작성합니다.

IF-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): 
    } 
+0

감사합니다. 작동합니다. :) – user3602008