📄 c--.y
字号:
%{
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#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 <value> type_spec
%type <_sym> var
%type <_sym> fun_declar
%type <_sym> fun_tag
%type <value> params
%type <value> param
%type <value> param_list
%type <value> args
%type <value> 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -