在上一节中,我们探讨了左结合和右结合,实现了a=b=3
这一类的语句,在这一节中,我们将会实现注释和定义变量时赋值。
SysY 语言中注释的规范与 C 语言一致,如下:
- 单行注释:以序列
//
开始,直到换行符结束,不包括换行符。 - 多行注释:以序列
/*
开始,直到第一次出现*/
时结束,包括结束处*/
。
修改词法分析
这是一个比较简单的问题,我们只需要识别出//
、/*
和*/
然后跳过其中的内容即可。
case '/':
c = get_nextchr();
switch (c)
{
case '/': single_annotation(); break;
case '*': block_annotation(); break;
default: t->token = T_DIV; put_backchr(c);break;
}
break;
单句注释扫描函数:
// 单句注释扫描函数
void single_annotation()
{
char strbuf[MAXINTS];
fgets(strbuf, MAXINTS, Infile);
Line++;
scan(&Token);
}
多句注释扫描函数:
// 多句注释扫描函数
void block_annotation()
{
char c;
while(1)
{
c = fgetc(Infile);
if(c == '*')
{
c = fgetc(Infile);
if(c == '/')
{
scan(&Token);
return;
}
}
if (c == '\n') Line++;
}
}
接下来处理定义变量时赋值的问题,这也是个简单的问题,只要在定义变量时往后看一个字符,如果是’='运算符,则为其定义并初始化。
修改语法分析
// 分析变量声明
void var_declaration(int type)
{
/*......省略操作......*/
while(1)
{
id = add_global(Text, P_INT, S_VARIABLE, 0);
// 如果下一个是"=",为变量赋初值,
// 否则,只定义变量
if(Token.token == T_EQU)
{
scan(&Token);
if(Token.token != T_INT)
{
fprintf(stderr, "Error token != T_INT on line %d\n", Line);
exit(1);
}
arm_global_symassign(Text, Token.intvalue);
scan(&Token);
}
else
{
arm_global_sym(Text);
}
// 如果下一个单词是";",则返回
if(Token.token == T_SEM)
{
scan(&Token);
return ;
}
/*......省略操作......*/
}
}
修改汇编代码
因为带初值的全局变量定义有专用的语句,所以我们新增一个生成定义并赋初值全局变量的函数。
// 生成全局变量符号表,且赋初始值
void arm_global_symassign(char *name, int n)
{
fprintf(Outfile, "\t.text\n\t.global %s\n\t.data\n\t.align 2\n\t.type i, %%object\n\t.size i, 4\n%s:\t.word %d\n", name, name, n);
}
测试结果
输入:
int a = 4, b = 3; // a = 4, b = 3
/*计算a+b的值,
并打印在频幕上*/
int main()
{
print a + b;
return a + b;
}
输出(out.s):
.text
.global __aeabi_idiv
.section .rodata
.align 2
.LC0:
.ascii "%d\012\000"
.text
.global a
.data
.align 2
.type i, %object
.size i, 4
a: .word 4
.text
.global b
.data
.align 2
.type i, %object
.size i, 4
b: .word 3
.text
.align 2
.globl main
.type main, %function
main:
push {fp, lr}
add fp, sp, #4
sub sp, sp, #8
str r0, [fp, #-8]
ldr r3, .L2+0
ldr r4, [r3]
ldr r3, .L2+4
ldr r5, [r3]
add r4, r4, r5
mov r1, r4
ldr r0, .L3
bl printf
ldr r3, .L2+0
ldr r4, [r3]
ldr r3, .L2+4
ldr r5, [r3]
add r4, r4, r5
mov r0, r4
b L1
L1:
sub sp, fp, #4
pop {fp, pc}
.align 2
.L3:
.word .LC0
.L2:
.word a
.word b
输出(out):
7
总结
在这一节中,我们实现了两个简单的功能,注释和定义变量并赋初值。在下一节中,我们将尝试更加困难的数组操作。