📄 c--.y
字号:
sprintf(&code[len]," cmp edx , dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);
len = strlen(code);
if(strcmp(rop,"le")==0) sprintf(&code[len]," jg short ");
else if(strcmp(rop,"l")==0) sprintf(&code[len]," jge short ");
else if(strcmp(rop,"g")==0) sprintf(&code[len]," jle short ");
else if(strcmp(rop,"ge")==0) sprintf(&code[len]," jl short ");
else if(strcmp(rop,"e")==0) sprintf(&code[len]," jne short ");
else if(strcmp(rop,"ne")==0) sprintf(&code[len]," jne short ");
len = strlen(code);
}
$$.code = (char *)malloc(len + 1);
strcpy($$.code,code);
}
}
}
| add_expr
{ $$ = $1; }
;
add_expr : add_expr addop term
{
char code[1000];
int len;
char *op;
if ($1.is_const && $3.is_const) { /* constant folding 均为常量*/
$$.is_const = 1;
if($1.type != INT && $1.type != CHAR || $3.type != INT && $3.type != CHAR ){
fprintf(errfile,"line %d : type unexpected \n",nline);
is_error++;
return 0 ;
}
else{
$$.type = INT;
if ($2 == '+') $$.value = $1.value + $3.value; // .value属性表示其值
else $$.value = $1.value - $3.value;
}
}
else { // 存在未知变量
op = ($2 == '+')? "add" : "sub";
$$.place = newtemp(); // 申请一个临时变元t?
$$.is_const = 0;
is_one_var = 0;
/* load the first oprand(操作数) */
if ($1.is_const) sprintf(code, " mov eax, %d\n", $1.value);
else{
sprintf(code, " mov eax, dword ptr [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); //add eax, ..
else{
sprintf(&code[len], " %s eax, dword ptr [ebp-%d] ;%s\n", op,$3.place->offset+4,$3.place->name); // 或 sub eax, ...
}
len = strlen(code);
sprintf(&code[len]," mov dword ptr [ebp-%d], eax ;%s\n", $$.place->offset+4, $$.place->name);
/* mov [ebp-..],eax;%s 其中%s 为[]地址上对应的变元的name */
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
}
| term
;
term : term mulop unary_expr
{
char code[1000];
int len;
char *op;
if (verbose) fprintf(stderr, "term => term mulop unary_expr mulop=%c\n", $2);
if ($1.is_const && $3.is_const) { /* constant folding */
$$.is_const = 1;
if($1.type != INT && $1.type != CHAR || $3.type != INT && $3.type != CHAR ){
fprintf(errfile,"line %d : type unexpected \n",nline);
is_error++;
return 0;
}
else{
$$.type = INT;
if ($2 == '*') $$.value = $1.value * $3.value;
else if($2 == '/'){
if($3.value == 0) fprintf(errfile,"line %d : fatal error by 0\n",nline);
$$.value = $1.value / $3.value;
}
else $$.value = $1.value % $3.value;
}
}
else {
$$.place = newtemp(); // 申请一个临时变元t
$$.is_const = 0;
if($2 == '%') op = "mod"; //汇编好象没这个??
else op = ($2 == '*')? "mul" : "div";
if ($1.is_const) sprintf(code, " mov eax, %d\n", $1.value);
else{
sprintf(code, " mov eax, dword ptr [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); //add eax, ..
else{
sprintf(&code[len], " %s dword ptr [ebp-%d] ;%s\n", op,$3.place->offset+4,$3.place->name);
len = strlen(code);
}
sprintf(&code[len]," mov dword ptr [ebp-%d], eax ;%s\n", $$.place->offset+4, $$.place->name); // z这里只考虑没进位的情况,乘的结果保留在低位
/* mov [ebp-..],eax;%s 其中%s 为[]地址上对应的变元的name */
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
}
| unary_expr
;
unary_expr : unaryop unary_expr
{
char code [1000];
int len;
char *op;
trace("unary_expr => unaryop unary_expr\n");
if($2.is_const) {
$$.is_const = 1;
if($2.type != INT && $2.type != CHAR){
fprintf(errfile,"line %d : type unexpected \n",nline);
is_error++;
return 0;
}
else{
$$.type = INT;
if ($1 == '!'){
if($2.value == 1 ) $$.value = 0; // '!'
else $$.value = 0 ;
}
else
$$.value = 0 - $2.value;
}
}
else{
op = ($1 == '-')?"uminus":"not"; // 取反操作 汇编没这个符号??
$$.place = newtemp(); // 申请一个临时变元t
$$.is_const = 0;
if ($2.is_const) sprintf(code, " mov eax, %d\n", 0 - $2.value);
else{
sprintf(code, " mov eax,dword ptr [ebp-%d] ;%s\n", $2.place->offset + 4, $2.place->name);
}
len = strlen(code);
sprintf(&code[len], " mov dword ptr [ebp-%d], eax ;%s\n", $$.place->offset + 4, $$.place->name);
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
}
| factor
;
factor : '(' expr ')'
{ trace("factor => ( expr )\n");
$$ = $2;
}
| var
{
$$.is_const = 0;
$$.place = $1;
$$.type = $1->type;
$$.code = NULL;
}
| call
{
trace("factor => call\n");
$$.type = $1.place->ret;
if(is_funret){ // 有函数返回值
if($1.place->ret_const){ //返回的是常数
$$.is_const = 1;
$$.value = $1.place->retvalue;
}
else{
$$.is_const = 0;
$$.place = temp_ret;
}
is_funret = 0; // 这样处理不够恰当,当函数被多次调用时
}
$$.code = $1.code; //代码上传
}
| NUM
{
$$.is_const = 1;
$$.value = atoi($1);
$$.type = INT;
$$.code = NULL;
}
| STRING_LITERAL
{
char text[100];
int i = 0;
$$.is_const = 1;
$$.type = CHAR_POINT;
$$.aa = data_place; //不这样就经常会出现死循环
$$.place = $1;
$$.code = NULL;
strcpy(text,yytext);
while(text[i+1] != '\"'){
text[i] = text[i+1];
i++;
}
if(text[i-1]=='n' && text[i-2] == '\\'){ //有带回车 , \ 和 n是分开的字符
text[i-2] = '\0';
const_strings[n_const_strings].is_n = 1;
const_strings[n_const_strings].index = data_place;
const_strings[n_const_strings].value = (char *)malloc(strlen(text)+1);
strcpy(const_strings[n_const_strings].value,text);
//const_strings[n_const_strings].value = text;
data_place += strlen(text) + 2;
}
else{
text[i] = '\0';
const_strings[n_const_strings].is_n = 0;
const_strings[n_const_strings].index = data_place;
const_strings[n_const_strings].value = (char *)malloc(strlen(text)+1);
strcpy(const_strings[n_const_strings].value,text); //为什么这样才不会被改变
//const_strings[n_const_strings].value = text;
data_place += strlen(text) + 1;
}
//printf("%d %s\n",0,const_strings[0].value );
//printf("%d %s\n",1,const_strings[1].value );
n_const_strings++; //常量串的个数
}
| CHAR_LITERAL
{
$$.is_const = 1;
$$.place = $1;
$$.type = CHAR;
$$.value = yytext[0]; //字符可以当成是数
$$.code =NULL;
}
;
call : ID '(' args ')'
{
char code[1000]; //代码
symbol *p;
paramtp *i,*j;
int len,t;
int arg_num=0;
struct table * tp = table_stack[table_len-1];
trace("call => ID ( args )\n");
if((p = lookup_all($1 ,tp))==0){ //没找到有定义
fprintf(errfile,"line %d:%s error have not defined\n",nline,$1);
is_error++;
return 0;
}
else{ // 找到同名标识符
if(p->type == FUN_DEFINE || p->type == FUN_DECLAR){ // 定义或是声明
for(i = p->paramer,j = $3;i!=NULL &&j!=NULL;i=i->next,j=j->next){ // 检查参数
if(i->type != j->type) break;
arg_num++; //记录参数个数
}
if(i!=NULL || j!=NULL){
fprintf(errfile,"line %d : the type or number of function argvments is unexpected!\n",nline);
is_error++;
return 0;
}
else $$.place = p;
}
else{ // 找到的不是函数定义或声明,可能是普通变量
fprintf(errfile,"line %d :%s error have not define \n",nline,$1);
is_error++;
return 0;
}
}
/* 过程调用所对应的代码
......push ..
......push ..
......call .. */
if($3->code != NULL){
strcpy(code,$3->code); // push ... 函数参数 但是$3 没有.code ?
len = strlen(code);
t = is_C($1);
if(t==1){ //判断是否为C 的函数
sprintf(&code[len]," call _%s\n",$1);
len = strlen(code);
sprintf(&code[len]," pop ecx\n");
len = strlen(code);
sprintf(&code[len]," add esp,%d\n",4*arg_num);
}
else{
sprintf(&code[len]," call %s\n",$1);
len = strlen(code);
sprintf(&code[len]," add esp,%d\n",4*arg_num);
len = strlen(code);
}
}
else{
t= is_C($1);
if( t==1){ //判断是否为C 的函数
sprintf(&code[0]," call _%s\n",$1);
len = strlen(code);
sprintf(&code[len]," pop ecx\n");
}
else{
sprintf(&code[0]," call %s\n",$1);
len = strlen(code);
}
}
len = strlen(code);
$$.code = (char *)malloc(strlen(code)+1);
strcpy($$.code, code);
}
;
args : arg_list
{
trace("args => arg_list\n");
$$->code = $1->code;
}
|
{
trace("args => ε\n");
$$->code = NULL;
}
;
arg_list : arg_list ',' expr
{
int len;
char code[1000];
paramtp *i;
trace("arg_list => arg_list , expr\n");
i = (paramtp *)malloc(sizeof(paramtp));
$$ = i; /* 插入参数表 */
$$->next = $1;
$$->type = $3.type ;
if($3.code == NULL){
if($3.is_const){ /* 常量参数 */
if($3.type == INT) sprintf(code," push %d\n",$3.value);
else if($3.type == CHAR) sprintf(code," push '%c'\n",$3.value);
else{
if( $3.aa == 0) sprintf(code," push offset s@\n");
else sprintf(code," push offset s@+%d\n",$3.aa); //??偏移量如何求得
}
}
else{
sprintf(code," push dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name); // 变量
}
}
else{
strcpy(code,$3.code);
len = strlen(code);
if($3.is_const){
if($3.type == INT) sprintf(&code[len]," push %d\n",$3.value);
else if($3.type == CHAR) sprintf(&code[len]," push '%c'\n",$3.value);
else{
if( $3.aa == 0) sprintf(&code[len]," push offset s@\n");
else sprintf(&code[len]," push offset s@+%d\n",$3.aa); //??偏移量如何求得
}
}
else{
sprintf(&code[len]," push dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);
}
}
len = strlen(code);
strcat(code,$1->code); // $1 放在 $3 的后面,遵循从右向左压栈的顺序
len = strlen(code);
$$->code = (char *)malloc(len + 1);
strcpy($$->code,code);
}
| expr
{
int len;
char code[1000];
paramtp *i;
trace("arg_list => expr\n");
i = (paramtp *)malloc(sizeof(paramtp)); /* 插入参数表 */
$$ = i;
$$->next = NULL;
$$->type = $1.type;
if($1.code == NULL){
if($1.is_const){ /* 常量参数 */
if($1.type == INT) sprintf(code," push %d\n",$1.value);
else if($1.type == CHAR) sprintf(code," push '%c'\n",$1.value);
else{
if( $1.aa == 0) sprintf(code," push offset s@\n");
else sprintf(code," push offset s@+%d\n",$1.aa); //偏移量如何求得
}
}
else{
sprintf(code," push dword ptr [ebp-%d] ; %s\n",$1.place->offset+4,$1.place->name); //
}
}
else{ //前面的参数
strcpy(code,$1.code);
len = strlen(code);
if($1.is_const){
if($1.type == INT) sprintf(&code[len]," push %d\n",$1.value);
else if($1.type == CHAR) sprintf(&code[len]," push '%c'\n",$1.value);
else{
if( $1.aa == 0) sprintf(&code[len]," push offset s@\n");
else sprintf(&code[len]," push offset s@+%d\n",$1.aa); //??偏移量如何求得
}
}
else{
sprintf(&code[len]," push dword ptr [ebp-%d] ; %s\n",$1.place->offset+4,$1.place->name);
}
}
len = strlen(code);
$$->code = (char *)malloc(len + 1);
strcpy($$->code,code);
}
;
callconvent : CDECL
{ trace("callconvent => __cdecl\n"); }
| STDCALL
{ trace("callconvent => __stdcall\n"); }
;
addop : '+'
{ $$ = '+';}
| '-'
{ $$ = '-';}
;
relop : LE
{ trace("relop => <= \n"); $$.code = "le"; }
| LT
{ trace("relop => < \n"); $$.code = "l"; }
| GT
{ trace("relop => > \n"); $$.code = "g"; }
| GE
{ trace("relop => >= \n"); $$.code = "ge"; }
| EQ
{ trace("relop => == \n"); $$.code = "e"; }
| NE
{ trace("relop => !=\n"); $$.code = "ne";}
;
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 copyright(){
printf("* * * * * * * * C-- ComPiler * * * * * * * * * * *\n");
printf("Auther:JDWang 04120087 Complete Data: 07.08.30\n");
printf("Program Function:\n");
printf("Use the program ,you can compiler a c-- program ,and build\n");
printf("a masm program(call masm code).Then you use some tools(LINK...)\n");
printf("to create an executable file(...exe)\n");
printf("However,because of several reasons,the compiler is not integrated\n");
printf("There are maybe some that C can achieve but it not,for example:\n");
printf("you can main() in C ,but don't use it in my compiler but only\n");
printf("main(void),and if(j).. and so on. I think i can conplete all that\n");
printf("on some day but it still a hand work!\n\n");
printf("Usage: \n");
}
void help(void) {
fprintf(stderr, "c-- [-v] sourcefile [targetfile]\n");
exit(1);
}
int yyparse();
FILE *errfile;
int main(int argc, char **argv) {
time_t start, finish; //计时
char filename[256];
++argv;
--argc;
if((argc > 0) && (strcmp(argv[0], "-v") == 0)){ // c-- -v ....
verbose++;
++argv;
--argc;
}
if (argc > 0) { // c-- [-v] sourcefile ...
yyin = fopen(argv[0],"r"); /* argv[0] 为 soursefile */
if(yyin == NULL){
fprintf(stderr, "cannot open %s\n",argv[0]);
exit(1);
}
}
else{
copyright();
help(); // c-- [-v]
}
++argv;
--argc;
if(argc > 0) strcpy(filename, argv[0]); /* argv[0] 为 targetfile */
else { // 默认为c--.asm
char * dot;
strcpy(filename, argv[-1]); /* argv[-1] 为c-- */
dot = strrchr(filename, '.'); // strrchr
if (dot!= NULL) *dot = 0; /* '\0' */
strcat(filename, ".asm"); // c--.asm
}
if (verbose) yydebug = 1; //-v
yyout = fopen(filename,"w");
if(yyout== NULL) {
fprintf(stderr, "cannot open %s\n", filename);
exit(1);
}
errfile = fopen("errfile.txt","w+");
time(&start);
yyparse( ); //warning
time(&finish);
if(is_error == 0) fprintf(errfile," Congraduate You!\n Not any error in your file\n");
fprintf(stderr, "\nCompiling 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; } // yychar
else if (yychar == ID) errtok = yylval._ident;
else if (yychar < OR) errtok = tokens[yychar-257];
//else if (yychar == addop) errtok = (char *)yylval._op;
else{
sprintf(buf, "%d", yychar); errtok = buf;
}
fprintf(stderr, "%s at token %s in line %d\n", s, errtok, nline);
yyerrok;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -