📄 c--.y
字号:
//l
simple_expr : add_expr relop add_expr
{
// printf("here is me %%%%%%%%%%%\n");
trace("simple_expr => add_expr relop add_expr\n");
$$.type=INT;
// printf("simple_expr type is %d\n",$$.type);
if (($1.type == INT || $1.type == CHAR) && ($3.type == INT || $3.type == CHAR)) {
if($2=="<"){
if($1.value<$3.value){$$.value=1;}else $$.value=0;
}else if($2=="<="){
if($1.value<=$3.value){$$.value=1;}else $$.value=0;
}else if($2=="=="){
if($1.value==$3.value){$$.value=1;}else $$.value=0;
}else if($2==">"){
if($1.value>$3.value){$$.value=1;}else $$.value=0;
}else if($2==">="){
if($1.value>=$3.value){$$.value=1;}else $$.value=0;
}
}
if ($1.type != INT && $1.type != CHAR) {
printf("line %3d error: %s :illegal, left operand is not constant or character\n", nline, $2);
}
if ($3.type != INT && $3.type != CHAR) {
printf("line %3d error: %s :illegal, right operand is not constant or character\n", nline, $2);
}
}
| add_expr {
trace("simple_expr => add_expr\n");
if($1.value!=0) $$.value=0;else $$.value=1;
$$.type = $1.type;
// printf("simple_expr type is %d\n",$$.type);
}
;
add_expr : add_expr ADDOP term
{
trace("add_expr => add_expr ADDOP term\n");
$$.type = INT;
if ($1.type == INT && $3.type == INT) {
if ($2 == '+') {
$$.value = $1.value + $3.value;
} else {
$$.value = $1.value - $3.value;
}
}
if ($1.type != INT) {
printf("line %3d error: %c :illegal, left operand is not constant\n", nline, $2);
}
if ($3.type != INT) {
printf("line %3d error: %c :illegal, right operand is not constant\n", nline, $2);
}
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 == '+')? "add" : "sub";
$$.place = newtemp();
$$.is_const = 0;
/* load the first oprand */
if ($1.is_const) sprintf(code, " mov eax, %d\n", $1.value); else
sprintf(code, " mov eax, [ebp-%d] ;%s\n", $1.place->offset+4, $1.place->name);
len = strlen(code);
if ($3.is_const) sprintf(&code[len], " %s eax, %d\n", op, $3.value); else
sprintf(&code[len], " %s eax, %s\n", op, $3.place->name);
len = strlen(code);
sprintf(&code[len], " mov [ebp-%d], eax ;%s\n", $$.place->offset+4, $$.place->name);
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
}
| term
{
$$.type = $1.type;
// printf("add_expr => term type is %d\n",$$.type);
trace("add_expr => term\n");
}
;
term : term mulop unary_expr
{ if (verbose) fprintf(stderr, "term => term mulop unary_expr mulop=%c\n", $2);
trace("term => term mulop unary_expr \n");
$$.type = INT;
if ($1.type == INT && $3.type == INT) {
if ($2 == '*') {
$$.value = $1.value * $3.value;
} else if ($2 == '/') {
$$.value = $1.value / $3.value;
} else {
$$.value = $1.value % $3.value;
}
}
if ($1.type != INT) {
printf("line %3d error: %c :illegal, left operand is not constant\n", nline, $2);
}
if ($3.type != INT) {
printf("line %3d error: %c :illegal, right operand is not constant\n", nline, $2);
}
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; /* does not handle '%' yet */
} else {
char code [1000];
int len;
char * op = ($2 == '*')? "mul" : "div";
$$.place = newtemp();
$$.is_const = 0;
/* load the first operand */
if ($1.is_const) sprintf(code, " mov eax, %d\n", $1.value); else
sprintf(code, " mov eax, [ebp-%d] ;%s\n", $1.place->offset+4, $1.place->name);
len = strlen(code);
if ($3.is_const) sprintf(&code[len], " %s eax, %d\n", op, $3.value); else
sprintf(&code[len], " %s eax, %s\n", op, $3.place->name);
len = strlen(code);
sprintf(&code[len], " mov [ebp-%d], eax ;%s\n", $$.place->offset+4, $$.place->name);
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
}
| unary_expr {
$$.type = $1.type;
// printf("term =>unary_expr type is %d\n",$$.type);
trace("term =>unary_expr \n");
}
;
unary_expr : unaryop unary_expr
{ trace("unary_expr => unaryop unary_expr\n");
$$.type = INT;
if ($2.type == INT) {
if ($1 == '!') {
if($2.value==0) $$.value=1;else $$.value=0;
} else {
$$.value = -$2.value;
}
}
if ($2.type != INT) {
printf("line %3d error: %c :illegal, right operand is not constant\n", nline, $1);
}
if($1=='!')
if($2.value==0) $$.value=1;else $$.value=0;
else if($1=='-') $$.value =-$2.value;
}
| factor
{
trace("unary_expr => factor\n");
$$.value=$1.value;
$$.type = $1.type;
// printf("unary_expr =>factor type is %d\n",$$.type);
}
;
factor : '(' expr ')'
{ trace("factor => ( expr )\n"); $$.value=$2.value;$$.type = $2.type; }
| var
{ trace("factor => var\n"); $$.is_const = 0; $$.place = $1; $$.type = $1->type; }
| call
{ trace("factor => call\n"); $$.value=$1.value; $$.type = $1.type; // printf("factor>>call type is %d\n",$$.type);
}
| NUM
{ trace("factor => NUM\n"); $$.is_const = 1; $$.value = atoi($1); $$.type = INT; }
| STRING {
trace("factor => STRING \n");$$.type=CHAR;
}
| CHARATER{
trace("factor => CHARATER \n"); $$.type=CHAR;
}
;
call : ID '(' args ')'
{
symbol *tmp = lookup($1, table_stack[table_len-1]);
trace("call => ID ( args )\n");
if(0!=tmp) { $$.type=tmp->type; }
// printf(" fun call args is %d\n",$3);
// printf(" call >> id type is %d\n",$$.type);
if (0 == tmp) {
printf("line %3d error: %s :undeclared function\n", nline, $1);
}
else {
fun_type *p1=tmp->functype,*p2=funtype;int i;
//printf("args %d ===%d \n",$3,tmp->funargc);
if(tmp->funargc>$3) printf("line %d Too fewer (%d)parameters in call to fuction of %s \n",nline,tmp->funargc-$3,tmp->name);
else if(tmp->funargc<$3) printf("line %d Too much (%d)parameters in call to fuction of %s \n",nline,$3-tmp->funargc,tmp->name);
for(i=1;i<=$3;i++)
{
if(p1==0||p2==0) break;
if(p1->type!=p2->type) printf("line %d Parater %d Type mismatch in call to fuction of %s \n",nline,i,tmp->name);
p1=p1->next; p2=p2->next;
}
}
funtype=0;
$$.code = malloc(1000);
sprintf($$.code, " push ...\n call %s\n", $1);
}
;
args : arg_list
{ $$=$1;trace("args => arg_list\n"); }
|
{ $$=0; trace("args => ε\n"); }
;
arg_list : arg_list ',' expr
{
fun_type *tmp; fun_type *pp;
tmp=(fun_type *)malloc(sizeof(fun_type));
tmp->type=$3.type;
tmp->next=0;
if(funtype==0) {
funtype=tmp;
}
else {
pp=funtype;
while(pp->next){
pp=pp->next;
}
pp->next=tmp;
}
$$=$1 + 1;
trace("arg_list => arg_list , expr\n");
}
| expr
{
fun_type *tmp; fun_type *pp;
tmp=(fun_type *)malloc(sizeof(fun_type));
tmp->type=$1.type;
tmp->next=0;
if(funtype==0) {
funtype=tmp;
}
else {
pp=funtype;
while(pp->next){
pp=pp->next;
}
pp->next=tmp;
}
$$=1;trace("arg_list => expr\n");
}
;
callconvent : CDECL
{ trace("callconvent => __cdecl\n"); }
| STDCALL
{ trace("callconvent => __stdcall\n"); }
;
/* |
{ trace("callconvent => ε \n"); }
;*/
relop : LE
{ trace("relop => <= \n"); }
| LT
{ trace("relop => < \n"); }
| GT
{ trace("relop => > \n"); }
| GE
{ trace("relop => >= \n"); }
| EQ
{ trace("relop => == \n"); }
| NE
{ trace("relop => !=\n"); }
;
mulop : '*'
{ trace("mulop => * \n"); $$ = '*'; }
| '/'
{ trace("mulop => / \n"); $$ = '/'; }
| '%'
{ trace("mulop => % \n"); $$ = '%'; }
;
unaryop : '!'
{ trace("unaryop => !\n"); $$ = '!'; }
| '-'
{ trace("unaryop => -\n"); $$ = '-'; }
;
%%
#include "lex.yy.c"
#include <time.h>
void help(void) { fprintf(stderr, "c-- [-v] sourcefile [targetfile]\n"); exit(1); }
int main(int argc, char **argv) {
time_t start, finish;
char filename[256];
++argv;
--argc;
if((argc > 0) && (strcmp(argv[0], "-v") == 0)) { verbose++; ++argv; --argc; }
if (argc > 0) yyin = fopen(argv[0],"r"); else help();
++argv;
--argc;
if(argc > 0) strcpy(filename, argv[0]);
else {
char * dot;
strcpy(filename, argv[-1]);
dot = strrchr(filename, '.');
if (dot != NULL) *dot = 0;
strcat(filename, ".asm");
}
yyout = fopen(filename, "w");
if (yyout == NULL) { fprintf(stderr, "cannot open %s\n", filename); exit(1); }
if (verbose) yydebug = 1;
time( &start );
yyparse( );
time( &finish );
fprintf(stderr, "compiling to %s, takes %1.1f seconds.\n", filename, difftime( finish, start ));
return 0;
}
yyerror(char *s) {
static char * tokens[]={"ID", "NUM", "INT", "VOID", "CHAR", "if", "else", "while", "return", "cdecl",
"stdcall", "=", "!=", "<", ">", "<=", ">=", "and", "or"};
char *errtok, buf[256];
if (yychar < 256) { sprintf(buf, "%c", yychar); errtok = buf; } else
if (yychar == ID) errtok = yylval._ident; else
if (yychar < OR) errtok = tokens[yychar-257]; else
if (yychar == ADDOP) errtok = yylval._op; else
{ sprintf(buf, "%d", yychar); errtok = buf; }
fprintf(stderr, "line %d :%s at token %s \n", nline,s, errtok);
yyerrok;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -