📄 c--.y
字号:
ttp = insert($2,tp); //插入
$$ = ttp;
}
}
| ID
{
struct table *tp = table_stack[table_len-1];
symbol *ttp;
trace("fun_tag => callconvent ID\n");
if((ttp = lookup_all($1,tp))!=0){ //已经在符号表出现(声明)
if(ttp->type == FUN_DECLAR){ //函数声明
$$ = ttp;
}
else if(ttp->type == FUN_DEFINE){ //先定义
fprintf(errfile,"line %d : function %s define repeatedly\n",nline,$1);
is_error++;
$$ = NULL;
}
else{ // 函数名可能和一变量名相同
fprintf(errfile,"line %d : warning the function argvment(s) is expected\n");
$$ = NULL;
}
}
else{
ttp = insert($1,tp); //插入
$$ = ttp;
}
}
;
params : param_list
{
trace("params => param_list \n");
offset_stack[offset_len-1] = 0;
$$ = $1;
}
| VOID
{ $$ = 0; }
;
param_list : param_list ',' param
{ trace("param_list => param_list , param \n");
$$ = $3;
$$->next = $1; /*c-- 函数参数从右到左顺序压栈*/
}
| param
{ trace("param_list => param\n");
$$ = $1;
}
;
param : type_spec ID
{
struct table * tp = table_stack[table_len-1]; //当前层
symbol *p;
int width;
paramtp *i;
trace("param => type_spec ID\n");
if(lookup($2,tp)!=0){
fprintf(errfile,"line %d : %s had been defined!",nline,$2);
is_error++;
return 0;
}
else{
p = insert($2,tp); //可能在此时创建一个新的符号表
width = 0; //类型长度
p->isargv = 1;
p->offset = offset_stack[offset_len-1];
p->type = $1;
if($1 == INT){
width = 4;
}
else if($1 == CHAR){
width = 1;
}
offset_stack[offset_len-1] += width;
i = (paramtp *)malloc(sizeof(paramtp)); /*插入参数表*/
$$ = i;
$$->next = NULL;
$$->type = p->type ;
}
}
| type_spec '*' ID
{
struct table *tp = table_stack[table_len-1]; //当前层
symbol *p;
int width;
paramtp *i;
trace("param => type_spec * ID \n");
if(lookup($3,tp)!=0){
fprintf(errfile,"line %d : %s had been defined!",nline,$3);
is_error++;
return 0;
}
else{
p = insert($3,tp);
width = 0; //类型长度
p->isargv = 1;
p->offset = offset_stack[offset_len-1];
if($1 == INT){
width = 4;
p->type = INT_POINT;
}
else if($1 == CHAR){
width = 4;
p->type = CHAR_POINT;
}
else if($1 == VOID){
width = 4;
p->type = VOID_POINT;
}
offset_stack[offset_len-1] += width;
i = (paramtp *)malloc(sizeof(paramtp)); /*插入参数表*/
$$ = i;
$$->type = p->type;
$$->next = NULL;
}
}
| type_spec ID '[' ']'
{
struct table * tp = table_stack[table_len-1]; //当前层
symbol *p;
int width;
paramtp *i;
trace("param => type_spec ID [ ]\n");
if(lookup($2,tp)!=0){
fprintf(errfile,"line %d : %s had been defined!",nline,$2);
is_error++;
return 0;
}
else{
p = insert($2,tp);
width = 0; //类型长度
p->isargv = 1;
p->offset = offset_stack[offset_len-1];
if($1 == INT){
width = 4;
p->type = INT_ARRAY;
}
else if($1 == CHAR){
width = 4;
p->type = CHAR_ARRAY;
}
offset_stack[offset_len-1] += width;
i = (paramtp *)malloc(sizeof(paramtp)); /*插入参数表*/
$$ = i;
$$->next = NULL;
$$->type = p->type;
}
}
;
comp_stmt : '{' local_declars stmt_list '}'
{
is_first++;
if(is_first==1) fprintf(yyout," .code\n");
if(is_funret){ //函数有返回值
if($3.is_const){
$$.is_const = 1;
$$.value = $3.value;
}
else{
$$.is_const =0;
}
}
$$.code = $3.code;
}
;
local_declars : local_declars var_declar
|
{ trace(" local_declars => ε\n"); }
;
stmt_list : stmt_list stmt
{
char code[1000];
if(is_funret){ //函数有返回值
if($2.is_const){
$$.is_const = 1;
$$.value = $2.value;
}
else{
$$.is_const =0;
}
}
if($1.code != NULL && $2.code != NULL){
$$.code = (char *)malloc(strlen($1.code) + strlen($2.code)+1);
strcpy(code,$1.code);
strcat(code,$2.code);
strcpy($$.code,code);
}
else if($1.code != NULL && $2.code == NULL) {
$$.code = (char *)malloc(strlen($1.code) +1);
strcpy(code,$1.code);
strcpy($$.code,code);
}
else if($1.code == NULL && $2.code != NULL) {
$$.code = (char *)malloc(strlen($2.code) +1);
strcpy(code,$2.code);
strcpy($$.code,code);
}
else $$.code = "";
}
|
{
$$.code = "";
trace("empty stmt_list\n");
}
;
stmt : expr_stmt
{ trace("stmt => expr_stmt\n"); // 语句类型
}
| comp_stmt
{ trace("stmt => comp_stmt\n"); }
| if_stmt
{ trace("stmt => if_stmt\n"); }
| while_stmt
{ trace("stmt => while_stmt\n"); }
| return_stmt
{
trace("stmt => return_stmt\n");
if(is_funret){ //函数有返回值
if($1.is_const){
$$.is_const = 1;
$$.value = $1.value;
}
else{
$$.is_const =0;
}
}
//$$.code = $1.code;
}
;
expr_stmt : expr ';'
{
if(verbose) fprintf(stderr, "expr_stmt => expr \n");
$$ = $1;
}
| ';'
{ trace("expr_stmt => ;\n");
$$.code = "";
}
;
if_stmt : IF '(' expr ')' stmt %prec LOW_ELSE
{
char code[1000];
int len;
char *E_false;
trace("if_stmt => if ( expr ) stmt\n");
if($3.is_const){
if($3.value != 0 ){
if($5.code != NULL){
strcpy(code,$5.code);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code) ;
}
}
else $$.code = "";
}
else{
E_false = newlabel();
strcpy(code,$3.code);
len = strlen(code);
sprintf(&code[len],"%s\n",E_false);
len = strlen(code);
if($5.code != NULL){
strcat(code,$5.code);
len = strlen(code);
}
sprintf(&code[len],"%s:\n",E_false);
len = strlen(code);
$$.code = (char *)malloc(len + 1);
strcpy($$.code,code);
}
}
| IF '(' expr ')' stmt ELSE stmt
{
char code[1000];
int len;
char *E_false;
char *S_next;
trace("if_stmt => if ( expr ) stmt else stmt\n");
if($3.is_const){
if($3.value != 0 ){
if($5.code != NULL){
strcpy(code,$5.code);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code) ;
}
}
else{
if($7.code != NULL){
strcpy(code,$7.code);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code) ;
}
}
}
else{
E_false = newlabel();
S_next = newlabel();
strcpy(code,$3.code);
len = strlen(code);
sprintf(&code[len],"%s\n",E_false);
len = strlen(code);
if($5.code !=NULL){
strcat(code,$5.code); // 真
len = strlen(code);
}
sprintf(&code[len]," jmp %s\n",S_next);
len = strlen(code);
sprintf(&code[len],"%s:\n",E_false); //label E_false
len = strlen(code);
if($7.code != NULL){
strcat(code,$7.code); //假
len = strlen(code);
}
sprintf(&code[len],"%s:\n",S_next); // label S_next
len = strlen(code);
$$.code = (char *)malloc(len + 1);
strcpy($$.code,code);
}
}
;
while_stmt : WHILE '(' expr ')' stmt
{
char code[1000];
int len;
char *S_begin;
char *S_next;
trace("while_stmt => while ( expr ) stmt\n");
if($3.is_const){
if($3.value != 0){
S_begin = newlabel();
strcpy(code,S_begin);
len = strlen(code);
if($5.code != NULL){
strcat(code,$5.code);
len = strlen(code);
}
sprintf(&code[len]," jmp %s\n",S_begin);
len = strlen(code);
$$.code = (char *)malloc(len +1);
strcpy($$.code,code);
}
else $$.code = "";
}
else{
S_begin = newlabel();
S_next = newlabel();
//strcpy(code,S_begin); // 此处用两种都可以
sprintf(code,"%s:\n",S_begin);
len = strlen(code);
strcat(code,$3.code);
len = strlen(code);
sprintf(&code[len],"%s\n",S_next);
len = strlen(code);
if($5.code != NULL){
strcat(code,$5.code);
len = strlen(code);
}
sprintf(&code[len]," jmp %s\n",S_begin);
len = strlen(code);
sprintf(&code[len],"%s:\n",S_next);
len = strlen(code);
$$.code = (char *)malloc(len +1);
strcpy($$.code,code);
}
}
;
return_stmt : RETURN ';'
{
trace("return_stmt => return ; \n");
is_funret = 0;
}
| RETURN expr ';'
{
//char code[100];
trace("return_stmt => return expr ;\n");
is_funret = 1;
if($2.is_const){
$$.is_const = 1;
//sprintf(&code[0]," mov ebx , %d\n",$2.value);
$$.value = $2.value;
}
else{
$$.is_const = 0;
//sprintf(&code[0]," mov ebx , [ebp-%d] ; %s\n",$2.place->offset+4,$2.place->name);
temp_ret = $2.place; //临时存放返回的单元 可以改用ebx 寄存器来实现
}
//$$.code = (char *)malloc(strlen(code)+1);
//strcpy($$.code,code);
}
;
expr : var '=' expr
{
char code[1000];
int len;
if($1->type != $3.type){ /* 表达式类型检查 */
fprintf(errfile,"line %d : expression type wrong \n",nline);
is_error++;
return 0;
}
else{
$$.type = $1->type;
if ($3.is_const){ // expr为常量的情况
sprintf(code," mov edx , %d\n",$3.value);
len = strlen(code);
sprintf(&code[len], " mov dword ptr [ebp-%d], edx;%s\n", $1->offset+4,$1->name);
}
else {
if($3.code != NULL){
strcpy(code, $3.code);
len = strlen(code); /* $3 的代码接在 $1 的代码后面 */
sprintf(&code[len]," mov edx ,dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);
}
else {
sprintf(code," mov edx , dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name); // 一个操作数
}
len = strlen(code);
sprintf(&code[len], " mov dword ptr [ebp-%d] , edx ; %s\n", $1->offset+4,$1->name);
}
len =strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code, code);
}
}
| simple_expr
{ $$ = $1; }
;
var : ID
{
symbol *p;
struct table * tp = table_stack[table_len-1]; //当前层
if (verbose) fprintf(stderr, "look for %s\n", $1);
if( ( p = lookup_all($1,tp)) == 0){ /*所有层中查找不到*/
fprintf(errfile, "line %d : undeclared identifier: %s \n",nline,$1);
is_error++;
return 0;
}
else{
if( p->scope != level && p->isargv == 1){ /* 有找到,但是其他函数的形参 */
fprintf(errfile, "line %d : undeclared identifier: %s \n",nline,$1);
is_error++;
return 0;
}
else{
if(p->type != INT && p->type !=CHAR){ /* 类型只允许int char */
fprintf(errfile, "line %d : type unexpected\n:\n", nline);
is_error++;
return 0;
}
else $$ = p ; // 同为symbol 类型
}
}
}
| ID '[' expr ']'
{
symbol *p;
struct table * tp = table_stack[table_len-1];
trace("var => ID [ expr ]\n");
if(( p = lookup_all($1, tp)) == 0){
fprintf(errfile, "line %d :undeclared identifier: %s \n",nline,$1);
is_error++;
return 0;
}
/* 数组类型 */
if(p->type == INT_ARRAY) $$->type = INT;
else if(p->type == CHAR_ARRAY) $$->type = CHAR;
else if(p->type == INT_POINT_ARRAY) $$->type = INT_POINT;
else if(p->type == CHAR_POINT_ARRAY) $$->type = CHAR_POINT;
else{ //无其他类型
fprintf(errfile,"nline %d :type unexpected\n",nline);
is_error++;
return 0;
}
//....
}
;
simple_expr : add_expr relop add_expr
{
char rop[4];
char code[1000];
int len;
trace("simple_expr => add_expr relop add_expr\n");
if($1.type != INT && $1.type != CHAR || $3.type != INT && $3.type != CHAR){ //只允许int char型
fprintf(errfile,"line %d : type unexpected\n",nline);
is_error++;
return 0;
}
else{
$$.type = INT;
strcpy(rop,$2.code); //op
rop[strlen(rop)] = '\0';
if($1.is_const && $3.is_const){ //两个均是常数
if( (strcmp(rop,"le") == 0) && $1.value <= $3.value) $$.value = 1;
else if((strcmp(rop,"l") == 0) && $1.value < $3.value) $$.value = 1;
else if((strcmp(rop,"g") == 0) && $1.value > $3.value) $$.value = 1;
else if((strcmp(rop,"ge") == 0) && $1.value >= $3.value) $$.value = 1;
else if((strcmp(rop,"e") == 0) && $1.value == $3.value) $$.value = 1;
else if((strcmp(rop,"ne") == 0) && $1.value != $3.value) $$.value = 1;
else $$.value = 0;
}
else {
if(!$1.is_const && $3.is_const){
sprintf(code," mov edx ,dword ptr [ebp-%d] ; %s\n",$1.place->offset+4,$1.place->name);
len = strlen(code);
sprintf(&code[len]," cmp edx , %d\n",$3.value);
len = strlen(code);
if(strcmp(rop,"le")==0) sprintf(&code[len]," jg short ");
else if(strcmp(rop,"l")==0) sprintf(&code[len]," jge short ");
else if(strcmp(rop,"g")==0) sprintf(&code[len]," jle short ");
else if(strcmp(rop,"ge")==0) sprintf(&code[len]," jl short ");
else if(strcmp(rop,"e")==0) sprintf(&code[len]," jne short ");
else if(strcmp(rop,"ne")==0)sprintf(&code[len]," je short ");
len = strlen(code);
}
else if($1.is_const && !$3.is_const){
sprintf(code," mov edx ,dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);
len = strlen(code);
sprintf(&code[len]," cmp edx , %d\n",$1.value);
len = strlen(code);
if(strcmp(rop,"le")==0) sprintf(&code[len]," jl short ");
else if(strcmp(rop,"l")==0) sprintf(&code[len]," jle short ");
else if(strcmp(rop,"g")==0) sprintf(&code[len]," jge short ");
else if(strcmp(rop,"ge")==0) sprintf(&code[len]," jg short ");
else if(strcmp(rop,"e")==0) sprintf(&code[len]," jne short ");
else if(strcmp(rop,"ne")==0)sprintf(&code[len]," je short ");
len = strlen(code);
}
else{
sprintf(code," mov edx , dword ptr [ebp-%d] ; %s\n",$1.place->offset+4,$1.place->name);
len = strlen(code);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -