📄 c编译器.c
字号:
;
fun_tag : callconvent ID
{ fprintf(yyout, "fun_tag => callconvent ID\n"); }
| ID
{ $$ = insert($1, table_stack[table_len-1]); }
;
params : param_list {$$=1; offset_len++;offset_stack[offset_len-1]=0;}
| VOID
{ $$ = 0; }
| { $$ = 0; }
;
param_list : param_list ',' param{swap(offset_stack,offset_len-paramCounter,offset_len-1);}
| param
;
param : type_spec ID
{
paramCounter++;
int width;
struct table * tp = table_stack[table_len-1];
symbol * p = insert($2, tp);
p->type = $1;
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] = -R_ADD_LEN - len;
len += width;
p->offset = offset_stack[offset_len-1];
type = $1;
}
| type_spec '*' ID
| type_spec ID '[' ']'
{
paramCounter++;
int width;
struct table * tp = table_stack[table_len-1];
symbol * p = insert($2, tp);
p->type = $1;
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] = -R_ADD_LEN - len;
len += width;
p->offset = offset_stack[offset_len-1];
type = $1;
}
;
comp_stmt : '{' local_declars stmt_list '}'
{ $$ = $3; }
;
local_declars : local_declars var_declar
|
{ /*fprintf(yyout, " local_declars => ε\n"); */ }
;
stmt_list : stmt_list stmt
{ {char * s;
s = (char *)malloc(strlen($1.code) + strlen($2.code)+1);
strcpy(s, $1.code);
strcat(s, $2.code);
$$.code = s; /*内存没有释放!*/
}}
|
{ $$.code = ""; }
;
stmt : expr_stmt
| comp_stmt
| if_stmt
{
$$.code = (char *)malloc(strlen($1.code)+1);
strcpy($$.code,$1.code);
}
| while_stmt
| return_stmt
;
expr_stmt : expr ';'
{ $$=$1;
}
| ';'
{ fprintf(yyout, "expr_stmt => ;\n"); }
;
if_stmt : IF '(' expr ')' stmt
{
int len;
char code[1000];
sprintf(code,"%s\t.L%d\n%s",$3.code,lableCounter++,$5.code);
len = strlen(code);
sprintf(&code[len],".L%d:",lableCounter-1);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code);
}
| IF '(' expr ')' stmt ELSE stmt
{
int len;
char code[1000];
sprintf(code,"%s\t.L%d\n%s\tjmp\t.L%d\n",$3.code,lableCounter,$5.code,lableCounter+1);
lableCounter += 2;
len = strlen(code);
sprintf(&code[len],".L%d:%s.L%d:",lableCounter-2,$7.code,lableCounter-1);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code);
}
;
while_stmt : WHILE '(' expr ')' stmt
{
int len;
char code[1000];
sprintf(code,".L%d:",lableCounter++);
len = strlen(code);
sprintf(&code[len],"%s\t.L%d\n%s",$3.code,lableCounter++,$5.code);
len = strlen(code);
sprintf(&code[len],"\tjmp\t.L%d\n.L%d:",lableCounter-2,lableCounter-1);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code);
}
;
return_stmt : RETURN ';'
{
$$.code = (char *)malloc(5);
strcpy($$.code,"\0");
}
| RETURN expr ';'
{
int len;
char code[100];
//fprintf(stdout,"%s",$2.code);
sprintf(code,$2.code);
len = strlen(code);
$$.code = (char *)malloc(len+1);
strcpy($$.code,code);
}
;
expr : var '=' expr
{
char code [1000];
if ($3.is_const)
{
sprintf(code, " movl $%d,%d(ebp) #%s%d\n",$3.value, -$1->offset, $1->name,$1->offset);}
else
{
int len;
strcpy(code, $3.code);
len = strlen(code);
sprintf(&code[len], " movl eax,%d(ebp) #%s\n",-$1->offset,$1->name);
}
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
$1->value = $3.value;
}
| logic_expr
;
var : ID
{ $$ = lookup($1, table_stack[table_len-1]);
if ($$ == NULL) { fprintf(stderr, "undeclared identifier: %s in line %d\n", $1, nline); exit(1);}
}
| ID '[' expr ']'
{
symbol temp;
symbol* temp2;
$$ = &temp;
temp2 = lookup($1, table_stack[table_len-1]);
$$->offset = temp2->offset;
$$->type = temp2->type;
if ($$ == NULL)
{ fprintf(stderr, "undeclared identifier: %s in line %d\n", $1, nline); exit(1);}
if($$->type==INT)
$$->offset -= $3.value*4;
else if($$->type==CHAR)
$$->offset -= $3.value;
}
;
logic_expr : logic_expr OR logicand_expr ///new added productions!!
{ fprintf(yyout, "logic_expr => logic_expr OR logicand_expr\n"); }
| logicand_expr{$$.value = $1.value;}
;
logicand_expr : logicand_expr AND simple_expr
{ fprintf(yyout, "logicand_expr => logicand_expr AND simple_expr\n"); }
| simple_expr{$$.value = $1.value; }
;
simple_expr : add_expr relop add_expr
{
int len;
char code[1000];
strcpy(code, $1.code);
len = strlen(code);
sprintf(&code[len], " movl eax,ebx\n");
len = strlen(code);
sprintf(&code[len], $3.code);
len = strlen(code);
sprintf(&code[len], " cmp eax,ebx\n");
len = strlen(code);
$$.value = 0;
switch($2)
{
case EQ:
sprintf(&code[len], " jne");
if($1.value==$3.value)
$$.value = 1;
break;
case NE:
sprintf(&code[len], " je");
if($1.value!=$3.value)
$$.value = 1;
break;
case LT:
sprintf(&code[len], " jge");
if($1.value<$3.value)
$$.value = 1;
break;
case GT:
sprintf(&code[len], " jle");
if($1.value>$3.value)
$$.value = 1;
break;
case LE:
sprintf(&code[len], " jg");
if($1.value<=$3.value)
$$.value = 1;
break;
case GE:
sprintf(&code[len], " jl");
if($1.value>=$3.value)
$$.value = 1;
break;
}
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
| add_expr
;
add_expr : add_expr ADDOP term
{
if ($1.is_const && $3.is_const) { /* constant folding */
$$.is_const = 1;
if ($2 == '+')
$$.value = $1.value + $3.value;
else
$$.value = $1.value - $3.value;
} else {
char code [1000];
int len;
char * op = ($2 == '+')? "addl" : "subl";
$$.place = newtemp();
$$.is_const = 0;
sprintf(code,"%s",$1.code);
/* load the first oprand */
len = strlen(code);
if ($1.is_const) sprintf(&code[len], " movl $%d,eax\n", $1.value); else
sprintf(&code[len], " movl %d(ebp),eax #%s\n", -$1.place->offset, $1.place->name);
len = strlen(code);
if ($3.is_const) sprintf(&code[len], " %s $%d,eax\n", op, $3.value); else
sprintf(&code[len], " %s %d(ebp),eax #%s\n", op, -$3.place->offset,$3.place->name);
len = strlen(code);
sprintf(&code[len], " movl eax,%d(ebp) #%s\n", -$$.place->offset, $$.place->name);
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
if ($2 == '+')
$$.value = $1.value + $3.value;
else
$$.value = $1.value - $3.value;
}
}
| term
;
term : term mulop unary_expr
{
if($1.is_const && $3.is_const)
{
switch(mulopSign){
case '*':
$$.value = $1.value * $3.value;break;
case '/':
$$.value = $1.value / $3.value;break;
case '%':
$$.value = $1.value % $3.value;break;
}
}
else
{
char code [1000];
int len;
char * op;
if(mulopSign=='*') op = "mul";
else if(mulopSign=='/') op = "div";
else op = "mod";
$$.place = newtemp();
$$.is_const = 0;
/* load the first oprand */
if ($1.is_const) sprintf(code, " movl $%d,eax\n", $1.value); else
sprintf(code, " movl %d(ebp),eax #%s\n", -$1.place->offset, $1.place->name);
len = strlen(code);
if ($3.is_const) sprintf(&code[len], " %s $%d,eax\n", op, $3.value); else
sprintf(&code[len], " %s %d(ebp),eax #%s\n", op, -$3.place->offset,$3.place->name);
len = strlen(code);
sprintf(&code[len], " movl eax,%d(ebp) #%s\n", -$$.place->offset, $$.place->name);
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
}
| unary_expr
;
unary_expr : unaryop unary_expr
{ fprintf(yyout, "unary_expr => unaryop unary_expr\n"); }
| factor
{
char code[100];
if($1.is_const==0)
{
//用于区分是否是函数调用返回
if($1.place!=NULL)
sprintf(code," movl %d(ebp),eax\n",-$1.place->offset);
else
sprintf(code,$1.code);
}
else if($1.is_const==1)
sprintf(code," movl $%d,eax\n",$1.value);
$$.code = (char *)malloc(strlen(code)+1);
sprintf($$.code,code);
//fprintf(stdout,"code:%s",code);
}
;
factor : '(' expr ')' {$$.value = $2.value;}
| var
{ $$.is_const = 0; $$.place = $1; $$.value = $1->value;}
| call
| NUM
{ $$.is_const = 1; $$.value = atoi($1);}
;
call : ID '(' args ')'
{
int len,i;
char code[100];
strcpy(code,$3);
len = strlen(code);
for(i=SCounterStart;i<SCounter;i++)
{
sprintf(&code[len],"\tpushl\t$.LC%d\n",i);
len = strlen(code);
}
if(paramLen==0)
sprintf(&code[len]," call %s\n",$1);
else
sprintf(&code[len]," call %s\n addl $%d, esp\n",$1,16);
$$.code = (char *)malloc(strlen(code)+1);
sprintf($$.code,code);
$$.is_const = 0;
$$.place = NULL;
//fprintf(stdout,"%dnihao%s\n\n",paramLen,$$.code);
}
;
args : {SCounterStart=SCounter;paramLen=0;}arg_list {$$ = $2;}
| {$$ = "";paramLen=0;}
;
arg_list : arg_list ',' expr
{
int width;
if ($3.place->type==INT) width = 4; else if ($3.place->type==CHAR) width = 1;
paramLen += width;
int len;
char code[100];
strcpy(code,$1);
len = strlen(code);
sprintf(&code[len]," pushl %d(ebp)\n",-$3.place->offset);
$$ = (char *)malloc(strlen(code)+1);
sprintf($$,code);
}
| expr
{
int width;
if ($1.place->type==INT) width = 4; else if ($1.place->type==CHAR) width = 1;
paramLen += width;
char code[100];
sprintf(code," pushl %d(ebp)\n",-$1.place->offset);
$$ = (char *)malloc(strlen(code)+1);
sprintf($$,code);
}
| SSTRING
{
char code[500],temp[500];
int len;
copyString(code,data);
len = strlen(code);
sprintf(&code[len],".LC%d:\n\t.string",SCounter++);
len = strlen(code);
copyString(&code[len],$1);
len = strlen(code);
sprintf(&code[len],"\n");
copyString(&data[0],code);
strcpy(temp,"\tsubl\t$8, esp\n");
$$ = (char *)malloc(strlen(temp)+1);
sprintf($$,temp);
}
;
callconvent : CDECL
{ fprintf(yyout, "callconvent => __cdecl\n"); }
| STDCALL
{ fprintf(yyout, "callconvent => __stdcall\n"); }
;
/* |
{ fprintf(yyout, "callconvent => ε \n"); }
;*/
relop : LE
{ $$ = $1; }
| LT
{ $$ = $1; }
| GT
{ $$ = $1; }
| GE
{ $$ = $1; }
| EQ
{ $$ = $1; }
| NE
{ $$ = $1; }
;
mulop : '*'
{ mulopSign = '*'; }
| '/'
{ mulopSign = '/'; }
| '%'
{ mulopSign = '%'; }
;
unaryop : '!'
{ fprintf(yyout, "unaryop => !\n"); }
| '-'
{ fprintf(yyout, "unaryop => -\n"); }
;
%%
#include "lex.yy.c"
int main(int argc, char **argv) {
++argv;
--argc;
if(argc > 0)
yyin = fopen(argv[0],"r");
else
yyin = stdin;
++argv;
--argc;
if(argc > 0)
yyout = fopen(argv[0],"w");
else
yyout = stdout;
//yydebug = 1;
yyparse( );
return 0;
}
yyerror(char *s) {
fprintf(stderr, "%s at token %d in line %d\n", s, yychar, nline);
yyerrok;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -