%{ #include "c.h" #define code2(c1,c2) code(c1); code(c2) #define code3(c1,c2,c3) code(c1); code(c2); code(c3) %} %union { Symbol *sym; /* symbol table pointer */ Inst *inst; /* machine instruction */ double val; /* actual value */ } %token NUMBER ID BLTIN UNDEF PRINTF SCANF VOID MAIN %token WHILE IF THEN ELSE %type expr expr stmt asgn prlist stmtlist compstmt %type cond while end else elsepart colon colonpart %right ASSIGN /* the "=" operator */ %left GT GE LT LE EQ NE %left '+' '-' %left '*' '/' %left UNARYMINUS %right '^' /* exponentiation */ %% prog: VOID MAIN '(' ')' compstmt { code(STOP); fprintf(ap,"%d %s",(progp-progbase-1),"STOP\n"); return 0; } ; compstmt: '{' stmtlist '}' { $$=$2; } ; stmt: PRINTF '(' prlist ')' ';' { $$ = $3; } | SCANF '(' ID ')' ';' { $$ = code2(varread, (Inst)$3); fprintf(ap,"%d %s",(progp-progbase-2),"varread\n"); fprintf(ap,"%d %s\n",(progp-progbase-1),$3->name); } | while '(' cond ')' stmt end { code2(branch,(Inst)$1); /* unconditional branch to beginning */ fprintf(ap,"%d %s",(progp-progbase-2),"branch\n"); fprintf(ap,"%d %d\n",(progp-progbase-1),$1-progbase); ($3)[0] = (Inst)$6; /* fixup conditional branch */ fprintf(ap,"%s %d","fixup location ",(&$3[0] - progbase)); fprintf(ap,"%s %d\n"," with ",($6 - progbase)); } | IF '(' cond ')' stmt elsepart {($3)[0] = (Inst)$6; fprintf(ap,"%s %d","fixup location ",(&$3[0] - progbase)); fprintf(ap,"%s %d\n"," with ",($6 - progbase)); } | '{' stmtlist '}' { $$ = $2; } | cond '?' stmt colonpart {($1)[0] = (Inst)$4; fprintf(ap,"%s %d","fixup location ",(&$1[0] - progbase)); fprintf(ap,"%s %d\n"," with ",($4 - progbase)); } | asgn ';' ; elsepart: else stmt {($1)[0] = (Inst)progp; /* fixup branch */ fprintf(ap,"%s %d","fixup location ",(&$1[0] - progbase)); fprintf(ap,"%s %d\n"," with ",(progp- progbase)); $$ = $1+1;} | {$$ = progp;} ; else: ELSE {$$ = progp+1; code2(branch,STOP); fprintf(ap,"%d %s",(progp-progbase-2),"branch\n"); fprintf(ap,"%d %s",(progp-progbase-1),"0\n"); } ; colonpart: colon stmt {($1)[0] = (Inst)progp; /* fixup branch */ fprintf(ap,"%s %d","fixup location ",(&$1[0] - progbase)); fprintf(ap,"%s %d\n"," with ",(progp- progbase)); $$ = $1+1;} ; colon: ':' {$$ = progp+1; code2(branch,STOP); fprintf(ap,"%d %s",(progp-progbase-2),"branch\n"); fprintf(ap,"%d %s",(progp-progbase-1),"0\n"); } ; cond: expr { code2(cbranch,STOP); $$ = progp-1; fprintf(ap,"%d %s",(progp-progbase-2),"cbranch\n"); fprintf(ap,"%d %s",(progp-progbase-1),"0\n"); } ; while: WHILE { $$ = progp; } ; asgn: ID ASSIGN expr { code3(varpush,(Inst)$1,assign); fprintf(ap,"%d %s",(progp-progbase-3),"varpush\n"); fprintf(ap,"%d %s\n",(progp-progbase-2),$1->name); fprintf(ap,"%d %s",(progp-progbase-1),"assign\n"); $$ = $3; } ; stmtlist: stmt { $$ = progp; } | stmtlist stmt ; end: /* nothing */ { $$ = progp+2; } ; expr: NUMBER { $$ = code2(constpush, (Inst)$1); fprintf(ap,"%d %s",(progp-progbase-2),"constpush\n"); fprintf(ap,"%d %lf\n",(progp-progbase-1),$1->u.val); } | ID { $$ = code3(varpush, (Inst)$1, eval); fprintf(ap,"%d %s",(progp-progbase-3),"varpush\n"); fprintf(ap,"%d %s\n",(progp-progbase-2),$1->name); fprintf(ap,"%d %s",(progp-progbase-1),"eval\n"); } | BLTIN '(' expr ')' { $$=$3; code2(bltin, (Inst)$1->u.ptr); fprintf(ap,"%d %s",(progp-progbase-2),"bltin\n"); fprintf(ap,"%d %s\n",(progp-progbase-1),$1->name); } | '(' expr ')' { $$=$2; } | expr '+' expr { code(add); fprintf(ap,"%d %s",(progp-progbase-1),"add\n"); } | expr '-' expr { code(sub); fprintf(ap,"%d %s",(progp-progbase-1),"sub\n"); } | expr '*' expr { code(mul); fprintf(ap,"%d %s",(progp-progbase-1),"mul\n"); } | expr '/' expr { code(divv); fprintf(ap,"%d %s",(progp-progbase-1),"div\n"); } | expr '^' expr { code(power); fprintf(ap,"%d %s",(progp-progbase-1),"power\n"); } | '-' expr %prec UNARYMINUS { $$=$2; code(negate); fprintf(ap,"%d %s",(progp-progbase-1),"negate\n"); } | expr GT expr { code(gt); fprintf(ap,"%d %s",(progp-progbase-1),"gt\n"); } | expr GE expr { code(ge); fprintf(ap,"%d %s",(progp-progbase-1),"ge\n"); } | expr LT expr { code(lt); fprintf(ap,"%d %s",(progp-progbase-1),"lt\n"); } | expr LE expr { code(le); fprintf(ap,"%d %s",(progp-progbase-1),"le\n"); } | expr EQ expr { code(eq); fprintf(ap,"%d %s",(progp-progbase-1),"eq\n"); } | expr NE expr { code(ne); fprintf(ap,"%d %s",(progp-progbase-1),"ne\n"); } ; prlist: expr { code(prexpr); fprintf(ap,"%d %s",(progp-progbase-1),"prexpr\n"); } | prlist ',' expr { code(prexpr); fprintf(ap,"%d %s",(progp-progbase-1),"prexpr\n"); } ; %% /* end of grammar */ #include #define NPROG 2000 int lineno = 1; #include #include #include #include #include #include jmp_buf finish; FILE *ap; /* assembly language file pointer */ FILE *in; /* input file pointer */ FILE *out; /* output file pointer */ void fpecatch(int i); int main(int argc, char *argv[]) /* compile */ { int myfd, retval; while ((myfd = open(argv[1], O_RDONLY)) && errno == EINTR); if (myfd == -1) perror("File Open Failed"); else { if (dup2(myfd, STDIN_FILENO) == -1) { perror ("Failed to Duplicate Program File"); return 1; } while (retval = close(myfd) && errno == EINTR); if (retval == -1) perror("Failed to Close Program File"); init(); run(); return 0; } } run() /* execute until EOF */ { signal(SIGFPE, fpecatch); initcode(); ap = fopen("assy", "w"); printf("%s","CHICO STATE MINI C COMPILER................EXPERIMENTAL VERSION 6 - Sept 2004\n\n"); yyparse(); printf("%s","\n\nPROGRAM OUTPUT\n\n"); fclose(ap); if ((in = fopen("input", "r")) == NULL) { fprintf(stderr,"Can't open file %s\n", "\"input\""); } out = fopen("output", "w"); execute(progbase); fclose(in); fclose(out); } yyerror(s) /* report compile-time error */ char *s; { Inst *p = prog; warning(s, (char *) 0); fprintf(stderr, " near line %d\n", lineno); *p = STOP; } execerror(s,t) /* report run-time error */ char *s, *t; { warning(s, t); exit(1); } void fpecatch(int i) /* catch floating point exceptions */ { execerror("floating point exception", (char *) 0); } warning(s,t) /* print warning message */ char *s, *t; { fprintf(stderr, "%s", s); if (t) fprintf(stderr, " %s\n", t); else fprintf(stderr, "%s", "\n"); }