2014-05-09 2 views
0

의 바이트 코드를 생성하는 방법이 같은 규칙을 포함하는 문법이 : 나는 WHILE 바이트 코드에 규칙을 번역하는 방법을 모른다루프 명령

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

합니다.

stmt 
    : ID ':''=' expr 
     { 
      if(st.lookupType($ID.text) != $expr.type) { 
       throw new IllegalArgumentException("Type error on variable: " + $ID.text + ".");  
      } 
      int var = st.lookupAddress($ID.text); 
      code.emit(Opcode.ISTORE, var); 
     } 
    | 'print' '(' expr ')' 
     { 
      if($expr.type == Type.INTEGER) { 
       code.emit(Opcode.PRINT); 
      } 
      if($expr.type == Type.BOOLEAN) { 
       code.emit(Opcode.BPRINT);   
      } 
     } 
    | 'if' expr 
     { 
      if($expr.type != Type.BOOLEAN) 
       throw new IllegalArgumentException("Type error in '(expr)': expr is not a boolean."); 
      int ltrue = code.newLabel();  
     } 
     'then' 
     { 
      code.emit(Opcode.LABEL, ltrue); 
     } 
     s1 = stmt ('else' s2 = stmt)? 
    | 'while' expr 
     { 
      if($expr.type != Type.BOOLEAN) 
       throw new IllegalArgumentException("Type error in '(expr)': expr is not a boolean."); 
      //Bytecode generator 
      // CODE... 
     } 
     'do' 
     ( 
      s1 = stmt 
      { 
       int ltrue = code.newLabel();  
      } 
     )*  
    | 'begin' s1 = stmt (';' s2 = stmt)* 'end'  
    ; 

st는 심볼 테이블, 즉, 특정 변수의 유형을 포함하는 테이블입니다 : 지금, 나는이를 썼다.

내 문법에는 INTEGER 또는 BOOLEAN의 두 가지 유형 만있을 수 있습니다.

newLabel() 메서드는 단순히 카운터를 증가시키는 L1, L2, L3 등과 같은 문자열 인 새 레이블을 만드는 것 이상을 수행하지 않습니다.

code은 프로그램 파싱 동안 생성 된 바이트 코드 명령어를 저장하는 데이터 구조 (Vector <Instruction>) 인 CodeGenerator의 인스턴스입니다.

Instruction 클래스는 두 개의 필드 (opcodeoperand)로 구성되며 단일 바이트 코드 명령어를 나타냅니다.

WHILE과 같은 루프의 바이트 코드는 어떻게 생성합니까? 감사


수정 된 코드 :

'while' 
    { 
     int lloop = code.newLabel(); //label for loop 
     int ldone = code.newLabel(); //laber for done 
     code.emit(Opcode.LABEL, lloop); 
    } 
    expr 
    { 
     if($expr.type != Type.BOOLEAN) 
      throw new IllegalArgumentException("Type error in '(expr)': expr is not a boolean."); 
     code.emit(Opcode.GOTO, ldone); 
    } 
    'do' (stmt)* 
     code.emit(Opcode.GOTO, lloop); 
     code.emit(Opcode.LABEL, ldone); 
    } 
+0

이것은 매우 모호한 질문입니다. 우리는 당신의 명령어 세트가 어떻게 생겼는지조차 모릅니다. 그렇다면 while 루프에서 코드를 생성하는 방법을 어떻게 설명 할 수 있습니까? –

+0

@TheANTLRGuy 답변 주셔서 감사합니다. 명확하지 않은 점은 무엇입니까? 질문을 자세히 할 수 있습니다. – user3602008

+0

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html – Holger

답변

0

while 루프의 가장 간단한 표현은 다음과 같습니다있다

'while' { 
       Create loop_label 
       Create done_label 
       Emit Label loop_label 
     } 
expr { 
       Emit Jump_If_False to done_label 
     } 
'do' stmt* { 
       Emit Jump to loop_label 
       Emit Label done_label 
     } 

:로 의사에 변환 할 수

LOOP: 
     <condition> 
     jmp_if_false DONE; 
     <body> 
     jmp LOOP 
DONE: 

에이 다양한 최적화가 가능하지만 적어도 시작일뿐입니다.

+0

고맙습니다. 귀하의 스키마에 따라 코드를 수정했습니다. ,하지만 여전히 작동하지 않습니다. 제발 도와 주실 래요? 수정 된 코드는 다음 대답에 있습니다. 감사합니다. – user3602008

+0

@ user3602008 : 중간 언어가 어떻게 생겼는지 전혀 알지 못해서 정말 도움이되지 않습니다. 그러나 중요한 부분은 done_label로 조건부로 점프해야한다는 것입니다. 무조건 점프는 (분명히) 시체를 건너 뜁니다. – rici

관련 문제