我的语法包含这样的规则:
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);
}
答案 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
}
有各种可能的优化,但这至少是一个开始。