如何生成循环指令的字节码

时间:2014-05-09 22:25:38

标签: antlr grammar bytecode

我的语法包含这样的规则:

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

我不知道如何将规则WHILE转换为字节码。现在,我写了这个:

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是CodeGenerator的一个实例,它是一个数据结构(Vector <Instruction>),用于存储在解析程序期间生成的字节码指令。

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);
    }

1 个答案:

答案 0 :(得分:0)

while循环的最简单表达式是:

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

可能会将伪代码转换为:

'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
        }

有各种可能的优化,但这至少是一个开始。