www.pudn.com > yufafenxiqi.rar > c--.y
%{
#include
#include
#include
#include
#include
#define HASHSIZE 128
//s
typedef struct aa
{ int type;
struct aa *next;
} fun_type;
typedef struct {
char *name; /* symbol name */
int scope; /* scope level */
int type;
int value;
int funargc;
fun_type *functype;
int isdeclar;
int offset; /* for functions: size of local variables */
} symbol ;
struct sym_entry {
symbol sym; /* this symbol */
struct sym_entry *next; /* next entry on hash chain */
};
struct table {
int level; /* scope level for this table */
struct table *previous; /* table at lower scope */
struct sym_entry *buckets[HASHSIZE]; /* hash buckets */
};
typedef struct
{
char op;
symbol *x, *y, *z;
} Quadruple;
typedef struct
{
char *translation;
int variable;
} myattribute;
struct string_data {
int index;
char * value;
};
int n_const_strings = 0;
struct string_data const_strings[100];
struct table * table_stack[100];
struct table * global_table;
int table_len = 0;
int offset_stack[100];
int offset_len = 0;
int level = 0;
int verbose = 0;
int argccount=0;
int isfunction=0;
int isdeclartion=0;
fun_type *funtype=0;
void trace(char *s) { if (verbose) fprintf(stderr, s); }
//0
symbol *lookup(char *name, struct table *tp) {
struct sym_entry *p;
unsigned h = ((unsigned)name)&(HASHSIZE-1); /*not素数 */
// printf("look up %s level %d tp.level %d table_len-1 %d\n",name,level,tp->level,table_len-1);
do
for (p = tp->buckets[h]; p; p = p->next)
if (name == p->sym.name) {return &p->sym;}
while (tp = tp->previous);
return 0;
}
symbol *lookupred(char *name, struct table *tp) {
struct sym_entry *p;
unsigned h = ((unsigned)name)&(HASHSIZE-1); /*not素数 */
for (p = tp->buckets[h]; p; p = p->next)
if (name == p->sym.name){//printf("find the symobl %s\n",p->sym.name);
return &p->sym;}
return 0;
}
struct table * mktable(struct table *previous, int level) {
int i;
struct table *new = (struct table *)malloc(sizeof *new);
new->previous = previous; new->level = level;
for (i = 0; i < HASHSIZE; i++) new->buckets[i] = 0;
return new;
}
//i
symbol *insert(char *name, struct table *tpp) {
unsigned h = ((unsigned)name)&(HASHSIZE-1);
struct table *tp = tpp;
struct sym_entry *p = (struct entry *)malloc(sizeof *p);
//printf("&&&&&&&&&tp->level =%d level=%d inserting %s\n", tp->level,level,name);
if (tp->level < level) { // 当前scope level
tp = mktable(tp, level);
// printf("make new table\n");
table_stack[table_len] = tp;
table_len ++;
offset_stack[offset_len] = 0;
offset_len ++;
}
p->sym.name = name; p->sym.scope = level;
if(isfunction) { p->sym.type = 1; }
else p->sym.type = 0; /*假设是常数, 常数的类型为0*/
p->next = tp->buckets[h];
p->sym.funargc=0;
tp->buckets[h] = p; /* 新名字在表头 */
//printf("Inset %s level %d tp.level %d table_len-1 %d\n",name,level,tp->level,table_len-1);
return &p->sym;
}
typedef struct {
int is_const;
int value;
int type;
symbol * place;
symbol * offset; /* for array */
char * code;
} expr;
char * insert_id(char *name);
symbol * newtemp()
{
static int index = 1;
char tmpname[20];
char * p;
symbol * s;
sprintf(tmpname, "__t%d", index);
index++;
s = insert(insert_id(tmpname), table_stack[table_len-1]);
s->offset = offset_stack[offset_len-1];
offset_stack[offset_len-1] += 4;
return s;
}
%}
%token ID NUM INT VOID CHAR IF ELSE WHILE RETURN
CDECL STDCALL EQ NE LT GT LE GE AND OR
ADDOP CHARATER STRING
%start program
%right '='
%left ADDOP
%left '*' '/'
%union{ char * _ident;
char _op;
char _relop[3];
int value;
symbol *_sym;
expr _expr;
};
%token <_ident> NUM
%token <_ident> ID
%token <_op> CHARATER
%token <_ident> STRING
%token <_op> ADDOP
%type type_spec
%type <_sym> var
%type <_sym> fun_declar
%type <_sym> fun_tag
%type params
%type param
%type param_list
%type args
%type arg_list
%type <_expr> factor
%type <_expr> unary_expr
%type <_expr> term
%type <_expr> add_expr
%type <_expr> simple_expr
%type <_expr> logicand_expr
%type <_expr> logic_expr
%type <_expr> expr
%type <_op> mulop
%type <_op> unaryop
%type <_relop> relop
//%token <_op> unaryop
/* 为了简单起见,把所有能产生代码的非终极符也说明为_expr类型,其实应该用别的,但是也有code属性*/
%type <_expr> comp_stmt
%type <_expr> if_stmt
%type <_expr> while_stmt
%type <_expr> stmt_list
%type <_expr> stmt
%type <_expr> expr_stmt
%type <_expr> return_stmt
%type <_expr> call
%%
program : M declar_list
{ fprintf(yyout, " .data\n");
{ int i;
struct sym_entry *p;
for (i = 0; i< n_const_strings; i++) {
fprintf(yyout, "s@%d label byte", const_strings[i].index);
fprintf(yyout, " db \"%s,0\"",const_strings[i].value); /* \n可能需要变成 10 */
}
/* 生成全局变量 */
for (i = 0; i< HASHSIZE; i++) {
p = global_table->buckets[i]; /* hash buckets */
while (p) {
if (p->sym.type == INT) fprintf(yyout, "_%s DD ?\n", p->sym.name); else
if (p->sym.type == CHAR) fprintf(yyout, "_%s DB ?\n", p->sym.name);
p = p->next;
}
}
fprintf(yyout, " public _main\n");
fprintf(yyout, " end\n");
}}
;
M : {
fprintf(yyout, " .386p\n");
fprintf(yyout, " model flat\n");
fprintf(yyout, " .code\n");
global_table = mktable(NULL, 0);
table_stack[table_len] = global_table;
table_len ++;
offset_stack[offset_len] = 0;
offset_len ++;
}
;
declar_list : declar_list declar
{ trace("declar_list => declar_list declar\n"); }
| declar
;
declar : var_declar
| fun_declar
;
var_declar : type_spec ID ';'
{
//1
struct table * tp = table_stack[table_len-1];
if(lookupred($2,tp)==0){
symbol * p = insert($2, tp);
int width = 0;
p->type = $1;
p->offset = offset_stack[offset_len-1];
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] += width;
}else printf("line %d: error: %s :redefinition\n", nline, $2);
trace("var_declar => type_spec ID ;\n");
} //12
| type_spec ID '[' NUM ']' ';'
{ struct table * tp = table_stack[table_len-1];
trace("var_declar => type_spec ID [ NUM ] ;\n");
if(lookupred($2,tp)==0){
symbol * p = insert($2, tp);
int width = 0;
int widthall=width;
p->type = $1;
p->offset = offset_stack[offset_len-1];
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] += widthall;
}else printf("line %3d error: %s :redefinition\n", nline, $2);
} //13
| type_spec '*' ID ';'
{ struct table * tp = table_stack[table_len-1];
trace(" var_declar => type_spec * ID ;\n");
if(lookupred($3,tp)==0){
symbol * p = insert($3, tp);
int width = 0;
int widthall=width;
p->type = $1;
p->offset = offset_stack[offset_len-1];
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] += widthall;
}else printf("line %3d error: %s :redefinition\n", nline, $3);
}
| type_spec '*' ID '[' NUM ']' ';'
{
struct table * tp = table_stack[table_len-1];
trace("var_declar => type_spec * ID [ NUM ] ;\n");
if(lookupred($3,tp)==0){
symbol * p = insert($3, tp);
int width = 0;
int widthall=width;
p->type = $1;
p->offset = offset_stack[offset_len-1];
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] += widthall;
}else printf("line %3d error: %s :redefinition\n", nline, $3);
}
| error '\n'
;
type_spec : INT
{ $$ = INT; //printf("type_spec %d\n",$$);
}
| VOID
{ $$ = VOID; //printf("type_spec %d\n",$$);
}
| CHAR
{ $$ = CHAR; //printf("type_spec %d\n",$$);
}
| error {fprintf(stderr, "line %d :type name expected\n",nline); yyerrok; }
;
//3
fun_declar : type_spec fun_tag '(' LL params ')' comp_stmt
{ fprintf(yyout, "_%s proc near\n", $2->name);
fprintf(yyout, " push ebp\n");
fprintf(yyout, " mov ebp,esp\n");
$2->offset = offset_stack[offset_len-1];
$2->type=$1;
// printf("function type is %d\n",$2->type);
fprintf(yyout, " sub esp, %d\n", $2->offset);
fprintf(yyout, "%s\n", $7.code);
fprintf(yyout, " .....\n");
fprintf(yyout, " ret\n");
fprintf(yyout, "_%s endp\n\n", $2->name);
printf("_%s :\n", $2->name);
if($2->isdeclar==1) {
fun_type *p1=$2->functype,*p2=funtype;int i;
if($2->funargc!=$5) printf(" Type mismatch(defined more than declartion) in redeclaration of %s\n",$2->name);
for(i=1;i<=$5;i++)
{
if(p1==0||p2==0) break;
if(p1->type!=p2->type)
printf(" Parater %d Type mismatch in redeclaration of %s\n",i,$2->name);
p1=p1->next; p2=p2->next;
}
}else {
$2->funargc=$5;
$2->functype=funtype;
// printf("%d = \n",$2->funargc);
}
offset_len--;
table_len--;
// printf(" argc %d\n", $5);
level--;
funtype=0;
// printf("Level -------- %d %d\n",level, table_len-1);
trace("fun_declar => type_spec fun_tag '(' LL params ')' comp_stmt \n");
}
| type_spec fun_tag '(' LL params ')' ';'
{
// fprintf(yyout, "extrn _%s:near\n", $2->name);
//55
trace("fun_declar => type_spec fun_tag '(' LL params ')' ';' \n");
// printf("ok here\n");
//printf("$5========= %d\n",$5);
$2->isdeclar=1;
$2->funargc=$5;
$2->functype=funtype;
funtype=0;
table_len--;
// printf("aideclar %d far %d\n", $2->isdeclar,$5);
level--;
// printf("end of function declar _%s \n\n", $2->name);
}
| type_spec fun_tag '(' LL params ')'
{
printf("line %d:function %s declaration missing ;\n",nline-1,$2->name);
}
;
//2
LL: ;{level++;trace("LL => ;\n"); insert(NULL, table_stack[table_len-1]);
// printf("Level -------- %d %d\n",level, table_len-1);
}
fun_tag : callconvent ID
{
struct table * tp = table_stack[table_len-1];
symbol *tmp;
isfunction=1;
trace("fun_tag => callconvent ID\n");
// printf("Before insert %s inserat level %d tp.level %d table_len-1 %d\n",$2,level,tp->level,table_len-1);
if((tmp=lookupred($2,tp))==0){
symbol * p;
$$ = insert($2, table_stack[table_len-1]);
}else {
$$=tmp;
if(tmp->type==1){
if(tmp->isdeclar==0) printf("line %d :error: %s :fuction redefinition\n", nline, $2);
else { $$=tmp ;}
}else
printf("line %d :error: %s :redefinition\n", nline, $2);
}
isfunction=0;
}
| ID
{
struct table * tp = table_stack[table_len-1];
symbol *tmp;
isfunction=1;
trace("fun_tag =>ID\n");
// printf("Before insert %s inserat level %d tp.level %d table_len-1 %d\n",$1,level,tp->level,table_len-1);
if((tmp=lookupred($1,tp))==0){
symbol * p;
$$ = insert($1, table_stack[table_len-1]);
}else {
$$=tmp;
if(tmp->type==1){
if(tmp->isdeclar==0) {printf("line %d :error: %s :fuction redefinition\n", nline, $1);}
else {$$=tmp ;}
}else
{printf("line %d :error: %s :redefinition\n", nline, $1);}
}
isfunction=0;
}
;
params : param_list
{ trace("params => param_list \n");
$$ = $1;
}
|VOID
{ trace("params => VOID \n"); argccount=0;
$$ = 0;
}
;
param_list : param_list ',' param
{ trace("param_list => param_list , param \n"); $$ = $1+$3; }
| param
{ trace("param_list => param\n"); $$ = $1; }
;
//22
param : type_spec ID
{ trace("param => type_spec ID\n");
$$ = 1;
{
struct table * tp = table_stack[table_len-1];
//33
if(lookupred($2,tp)==0){
symbol * p = insert($2, tp);
int width=0;
fun_type *tmp; fun_type *pp;
tmp=(fun_type *)malloc(sizeof(fun_type));
tmp->type=$1;
tmp->next=0;
if(funtype==0) {
funtype=tmp;
}
else {
pp=funtype;
while(pp->next){
pp=pp->next;
}
pp->next=tmp;
}
p->type = $1;
p->offset = offset_stack[offset_len-1];
// if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
//offset_stack[offset_len-1] -= width;
}else printf("line %d :error %s :redefinition\n", nline, $2);
}
$$ = 1; // printf("ok here\n");
}
| type_spec '*' ID
{ trace("param => type_spec * ID \n");
{
struct table * tp = table_stack[table_len-1];
if(lookupred($3,tp)==0){
symbol * p = insert($3, tp);
int width = 0;
fun_type *tmp; fun_type *pp;
tmp=(fun_type *)malloc(sizeof(fun_type));
tmp->type=$1;
tmp->next=0;
if(funtype==0) {
funtype=tmp;
}
else {
pp=funtype;
while(pp->next){
pp=pp->next;
}
pp->next=tmp;
}
p->type = $1;
p->offset = offset_stack[offset_len-1];
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] -= width;
}else printf("line %d :error: %s :redefinition\n", nline, $3);
} $$ = 1;
}
| type_spec ID '[' ']'
{ trace("param => type_spec ID [ ]\n");
{
struct table * tp = table_stack[table_len-1];
if(lookupred($2,tp)==0){
symbol * p = insert($2, tp);
int width = 0;
fun_type *tmp; fun_type *pp;
tmp=(fun_type *)malloc(sizeof(fun_type));
tmp->type=$1;
tmp->next=0;
if(funtype==0) {
funtype=tmp;
}
else {
pp=funtype;
while(pp->next){
pp=pp->next;
}
pp->next=tmp;
}
p->type = $1;
p->offset = offset_stack[offset_len-1];
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] -= width;
}else printf("line %d :error: %s :redefinition\n", nline, $2);
} $$ = 1;
}
;
//66
comp_stmt : '{' local_declars stmt_list '}'
{ $$ = $3; trace(" comp_stmt => local_declars stmt_list\n"); }
;
local_declars : local_declars var_declar
|
{ trace(" local_declars => ε\n"); }
;
stmt_list : stmt_list stmt
{ char * s;
trace(" stmt_list => stmt_list stmt \n");
$$=$2;
// assert($1.code != NULL);
// assert($2.code != NULL);
// s = (char *)malloc(strlen($1.code) + strlen($2.code)+1);
// strcpy(s, $1.code);
// strcat(s, $2.code);
// $$.code = s;
/*释放内存!*/
/*free($1.code); free($2.code); */
}
|
{ $$.code = ""; trace("empty stmt_list\n");}
;
stmt : expr_stmt
{ $$=$1; trace("stmt => expr_stmt\n"); }
| comp_stmt
{ $$=$1; trace("stmt => comp_stmt\n"); }
| if_stmt
{ $$=$1; trace("stmt => if_stmt\n"); }
| while_stmt
{ trace("stmt => while_stmt\n"); }
| return_stmt
{ $$=$1; trace("stmt => return_stmt\n"); }
;
expr_stmt : expr ';'
{
trace("expr_stmt => expr ;\n");
//77
/* if (verbose){
if($1.type==INT)
fprintf(stderr, "expr_stmt => expr ; type is int code=%d\n", $1.value);
else if($1.type==CHAR)
fprintf(stderr, "expr_stmt => expr ; type is char code=%s\n", $1);
}*/
$$=$1;
}
| ';'
{ trace("expr_stmt => ;\n"); }
;
if_stmt : IF '(' expr ')' stmt
{ trace("if_stmt => if ( expr ) stmt\n"); $$=$5; }
| IF '(' expr ')' stmt ELSE stmt
{ trace("if_stmt => if ( expr ) stmt else stmt\n"); $$.code="if------"; }
;
while_stmt : WHILE '(' expr ')' stmt
{ trace("while_stmt => while ( expr ) stmt\n"); }
;
return_stmt : RETURN ';'
{ trace("return_stmt => return ; \n"); }
| RETURN expr ';'
{ trace("return_stmt => return expr ;\n");
$$ = $2; }
;
expr : var '=' expr
{ char code [1000];
trace("expr => var '=' expr \n");
if ($1 != 0) {
if ($1->type != $3.type) {
// printf("var type is %d expr type is %d \n",$1->type,$3.type);
printf("line %d :error : = :the left and the right type does not match\n", nline, $1);
}
$$.type = $1->type;
}
/* if ($3.is_const) sprintf(code, " mov [ebp-%d], %d ;%s\n", $1->offset+4, $3.value, $1->name);
else { int len;
strcpy(code, $3.code);
len = strlen(code);
sprintf(&code[len], " mov %s, %s\n", $1->name, $3.place->name);
}
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
fprintf(yyout, code);
*/
}
| logic_expr{
trace("expr => logic_expr ; \n");
$$.type=$1.type;
// printf("expr => logic_expr type is %d \n",$$.type);
}
;
//4
var : ID
{ if (verbose) fprintf(stderr, "look for %s\n", $1);
$$ = lookup($1, table_stack[table_len-1]);
if ($$ == NULL) { fprintf(stderr, "line %d :undeclared identifier: %s \n", nline, $1);
}// else printf("var id type is %d \n",$$->type);
}
| ID '[' expr ']'
{ trace("var => ID [ expr ]\n");
$$ = lookup($1, table_stack[table_len-1]);
if ($$ == NULL) { fprintf(stderr, "line %d :undeclared identifier: %s \n", nline, $1);
//exit(0);
}
}
;
logic_expr : logic_expr OR logicand_expr ///new added productions!!
{ trace("logic_expr => logic_expr OR logicand_expr\n");
if($1.value||$3.value) $$.value=1;
else $$.value=0;
$$=$3;
}
| logicand_expr
{ trace("logic_expr => logicand_expr\n"); $$=$1;
//printf("expr => logic_expr type is %d \n",$$.type);
}
;
logicand_expr : logicand_expr AND simple_expr
{ trace("logicand_expr => logicand_expr AND simple_expr\n");
if($1.value&&$3.value) $$.value=1;
else $$.value=0;
$$.type=$3.type;
}
| simple_expr
{ trace("logicand_expr => simple_expr\n");
$$=$1;
//printf("ogicand_expr => simple_expr type is %d \n",$$.type);
}
;
//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
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;
}