的字節碼我有一個包含這樣的規則語法:如何產生循環指令
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
類由兩個字段(opcode
和operand
)組成,代表單字節代碼指令。
如何生成循環的字節碼,如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);
}
這是一個很模糊的問題,我很害怕。我們甚至不知道你的指令集是什麼樣的,所以我們如何告訴你如何從while循環生成代碼? –
@TheantLRGuy謝謝你的回答,有什麼不清楚的?我可以詳細說明問題。 – user3602008
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html – Holger