⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c编译器.c

📁 在c环境下的编译器 一.实验完成主要功能描述: 1.if语句 2.if_else语句 3.while语句 4.数组 5.函数调用 6.对外部函数printf的调用(用于打印) 二.测试
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include <string.h>

int nline = 1;

struct id_entry {
char * id;
struct id_entry *next; /* next entry on hash chain */
};

struct id_entry * id_hash_table[1024];

int hash(char * name) 
{
int h = *name++;
while (*name) h = h << 4 + *name++;
return h;
}

char * insert_id(char *name)
{ int h = hash(name) & 1024;
struct id_entry *p=id_hash_table[h];
while (p && (strcmp(p->id, name) != 0)) p = p->next;
if (p) return p->id;
p = (struct id_entry *)malloc(sizeof *p);
p->id = (char *)malloc(strlen(name)+1);
strcpy(p->id, name);
p->next = id_hash_table[h];
id_hash_table[h] = p; /* 新名字在表头 */
return p->id;
} 

%}

/*正规定义*/
delim [ \t]
ws {delim}+
leter [A-Za-z] 
digit [0-9]
id {leter}({leter}|{digit})* 
number {digit}+(\.{digit}+)?(E[+\-]?{digit}+)? 
comment (\#[^\n]*)|(\/\*(((\*)*[^\*\/]+(\/)*)*|(\*)*|(\/)*)\*\/)|(\/\/[^\n]*)
sentence \"(.)*\"
chartype (\'([^\n]|\n)\')|\'\'
special [\@\~\\\$\`] 
%%
"\n" { nline++;}
{comment} {/*对预处理和注释部分没有动作和返回值*/}
{ws} {/*对空白串没有动作和返回值*/}
{number} { yylval._ident = insert_id(yytext); return NUM;}
"__stdcall" {return STDCALL;}
"__cdecl" {return CDECL;}
"if" {return IF;}
"int" {return INT;}
"void" {return VOID;}
"char" {return CHAR;}
"else" {return ELSE;}
"while" {return WHILE;}
"return" {return RETURN;}
{id} { yylval._ident = insert_id(yytext); return ID;}
{sentence} { yylval._ident = insert_id(yytext); return SSTRING;}
"<=" {yylval.value = LE;return LE;}
">=" {yylval.value = GE;return GE;}
"<" {yylval.value = LT;return LT;}
">" {yylval.value = GT;return GT;}
"!=" {yylval.value = NE;return NE;}
"==" {yylval.value = EQ;return EQ;}
[+-] {yylval._op = yytext[0]; return ADDOP;}
. { return yytext[0]; }
%%

error(char *m)
{
fprintf(stderr,"%s\n",m);
exit(1); /*非正常终止*/
}

int yywrap(){return 1;}







yac.y

%{
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define HASHSIZE 128
#define MAX_CODE_SIZE 10000
#define R_ADD_LEN 8 //调用函数时用8的单元保存返回地址 

typedef struct {
char *name; /* symbol name */
int scope; /* scope level */
int type;
int value;
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;

typedef struct
{ char * name;
} fun_type;

typedef struct {
int type;
int size;
} global_data;

global_data globals[100];
int n_globals;

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 type; //暂时用作声明变量时的类型传递
char mulopSign; //暂时用作记录*,/,%.
int lableCounter = 0; //用作生成的汇编代码中标号的计数器
int SCounter = 0; //生成数据段中内容时用到的标号计数器
int SCounterStart = 0;
char data[500]; //生成数据段的代码
int len = 0; //用在将函数参数插入符号表时
int paramCounter = 0; //记录函数参数个数
int paramLen = 0; //函数参数总长度


symbol *lookup(char *name, struct table *tp) {
struct sym_entry *p;
unsigned h = ((unsigned)name)&(HASHSIZE-1); /*not素数 */
do
for (p = tp->buckets[h]; p; p = p->next)
if (name == p->sym.name) return &p->sym;
while (tp = tp->previous);
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;
}

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);
table_stack[table_len] = tp; 
table_len ++;
// offset_stack[offset_len] = 0;
// offset_len ++;
}

offset_stack[offset_len] = 0;
offset_len ++;

p->sym.name = name; p->sym.scope = level; p->sym.type = 0; /*假设是常数, 常数的类型为0*/
p->next = tp->buckets[h];
tp->buckets[h] = p; /* 新名字在表头 */
return &p->sym;
}

typedef struct {
int is_const;
int value; 
symbol * place;
symbol * offset; /* for array */
char * code;
} expr;

typedef struct {
int type;
} rr;


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] = offset_stack[offset_len-2]+4;
s->offset = offset_stack[offset_len-1];
return s;
}

//给寄存器名前加两个百分号
void addPS(char* d,char*s)
{
int i = 0;
char* p = s;
char* q = d;
while(*p!='\0')
{
if(*p=='e')
{
p++;
if(*p!='\t')
{*q = '%';q++;}
p--;
}
*q = *p;
q++;
p++;
}
*q = '\0';
}
//用于将调用函数参数插入符号表时,对各参数offset进行处理
void swap(int arr[],int s, int e)
{
int temp;
while(s<e)
{
temp = arr[s];
arr[s] = arr[e];
arr[e] = temp;
s++;
e--;
}
}
//字符串复制
void copyString(char* d, char*s)
{
while(*s!='\0')
*d++ = *s++;
*d='\0';
}
%}

%token ID NUM INT VOID CHAR IF ELSE WHILE RETURN 
CDECL STDCALL EQ NE LT GT LE GE AND OR 
ADDOP SSTRING
%start program

%right '='
%left ADDOP 
%left '*' '/' 

%union{ char * _ident;
char _op;
int value;
symbol *_sym; 
expr _expr;
rr _rr;
};

%token <_ident> NUM
%token <_ident> ID
%token <_ident> SSTRING
%token <_op> ADDOP
%token <value> EQ
%token <value> NE
%token <value> LT
%token <value> GT
%token <value> LE
%token <value> GE
%type <value> type_spec
%type <_sym> var
%type <_sym> fun_declar
%type <_sym> fun_tag
%type <value> params
%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 <_expr> comp_stmt
%type <_expr> stmt_list
%type <_expr> stmt
%type <_expr> expr_stmt
%type <_expr> if_stmt 
%type <_expr> while_stmt
%type <_expr> return_stmt
%type <_expr> call
%type <_ident> arg_list
%type <_ident> args

%type <value> relop 

%%
program : M declar_list
{ 
fprintf(stdout,"%s\n",data);
fprintf(yyout, " .ident \"GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)\"\n");
fprintf(yyout, " .section .note.GNU-stack,\"\",@progbits\n");
//fprintf(yyout, " .data\n");
{ int i;
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 */
}}
}
;
M : { 
global_table = mktable(NULL, 0); 
table_stack[table_len] = global_table; 
table_len ++;
offset_stack[offset_len] = 0;
offset_len ++;
fprintf(stdout," .section .rodata\n");
}
;
declar_list : declar_list declar 
{ /*fprintf(yyout, "declar_list => declar_list declar\n");*/ }
| declar
;
declar : var_declar 
| fun_declar
;
var_declar : type_spec ID 
{ 
struct table * tp = table_stack[table_len-1];
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+offset_stack[offset_len-2];
p->offset = offset_stack[offset_len-1];
type = $1;
} R
| type_spec ID '[' NUM ']' ';'
{ 
struct table * tp = table_stack[table_len-1];
symbol * p = insert($2, tp);
int width = 0;
p->type = $1;
if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1;
offset_stack[offset_len-1] = width*atoi($4)+offset_stack[offset_len-2];
p->offset = offset_stack[offset_len-1];
type = $1;
}
| type_spec '*' ID ';' 
{ fprintf(yyout, " var_declar => type_spec * ID ;\n"); }
| type_spec '*' ID '[' NUM ']' ';'
{ fprintf(yyout, "var_declar => type_spec * ID [ NUM ] ;\n"); }
;
R : ',' ID 
{ {
struct table * tp = table_stack[table_len-1];
symbol * p = insert($2, tp);
int width = 0;
p->type = type;
// p->offset = offset_stack[offset_len-1];
if (p->type == INT) width = 4; else if (p->type == CHAR) width = 1;
offset_stack[offset_len-1] += width+offset_stack[offset_len-2];
p->offset = offset_stack[offset_len-1];

}} R 
| ';'
;
type_spec : INT
{ $$ = INT; }
| VOID 
{ $$ = VOID; }
| CHAR
{ $$ = CHAR; }
;

fun_declar : type_spec fun_tag '(' params ')' {level++;} comp_stmt
{ 
fprintf(yyout, ".globl %s\n",$2->name);
fprintf(yyout, " .type %s, @function\n",$2->name);
fprintf(yyout, "%s:\n", $2->name); 
if(strcmp($2->name,"main"))
{
fprintf(yyout, " pushl %%ebp\n");
fprintf(yyout, " movl %%esp, %%ebp\n");
fprintf(yyout, " subl $16, %%esp\n");
}
else
{
fprintf(yyout, " pushl %%ebp\n");
fprintf(yyout, " movl %%esp, %%ebp\n");
fprintf(yyout, " subl $24, %%esp\n");
fprintf(yyout, " andl $-16, %%esp\n");
fprintf(yyout, " movl $0, %%eax\n");
fprintf(yyout, " addl $15, %%eax\n");
fprintf(yyout, " addl $15, %%eax\n");
fprintf(yyout, " shrl $4, %%eax\n");
fprintf(yyout, " sall $4, %%eax\n");
fprintf(yyout, " subl %%eax, %%esp\n");
}
//对得到的代码做处理,为寄存器名前加%
char code[MAX_CODE_SIZE];
addPS(code,$7.code);
fprintf(yyout, "%s", code);
fprintf(yyout, " leave\n");
fprintf(yyout, " ret\n");
fprintf(yyout, " .size %s, .-%s\n",$2->name,$2->name);
$2->offset = offset_stack[offset_len-1];
offset_len--;
table_len--;
level--;
}
| type_spec fun_tag '(' params ')' ';'{} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -