📄 parser.c
字号:
/* parser.c * * (C) Copyright Apr 15 1995, Edmond J. Breen. * ALL RIGHTS RESERVED. * This code may be copied for personal, non-profit use only. * */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <limits.h>#include "MachSet.h"#include "global.h"#include "lexer.h"#include "func.h"#include "typemod.h"#include "xalloc.h"#include "typesets.h"#include "cdecl.h"#include "error.h"#include "symbol.h"#include "parser.h"typedef struct { val_t match, loc;} pair_t;static int STRUCT_MEMBER_TYPE =0;#define out_expr Outexpr#define setInst(code,idx,mem,val) do { code_t *C__C = code;\ if(C__C->binst) \ C__C->inst[idx].mem = val;\ } while(0)void EiC_reset_env_pointers(token_t *e1,int bp);/** PROTOTYPES parser.c **/static void correctit(code_t * C, eicstack_t * S, int nxt, int loc);static void fixcasestack(token_t * e1, int nxt, int loc);static void block(token_t * e1);static void addinlocals(token_t * e1,int n);static void label_stmt(token_t * e1);static void testfortype(token_t *e1, int NoVoid);static void genJump(token_t *e1, val_t *v, int t,int T);static void select_stmt(token_t * e1);static void iter_stmt(token_t * e1);static void jump_stmt(token_t * e1);static void Outexpr(token_t * e1);static void expr(token_t * e1);static void log_or_expr(token_t * e1);static void log_and_expr(token_t * e1);static void inc_or_expr(token_t * e1);static void xor_expr(token_t * e1);static void and_expr(token_t * e1);static void equal_expr(token_t * e1);static void rel_expr(token_t * e1);static void shift_expr(token_t * e1);static void add_expr(token_t * e1);static void mult_expr(token_t * e1);static void cast_expr(token_t * e1);static void f_cast_expr(token_t * e1);static void EiC_unary_expr(token_t * e1);static void postfix_expr(token_t * e1);static void EiC_r_postfix_expr(token_t * e1);static int arg_expr_list(token_t * E1, token_t * e1);static void primary_expr(token_t * e1);static void process_binary(void (*func) (token_t * e), token_t * e1, int op);static void assignop(void (*func) (token_t * e), token_t * e1, int op);static int findmem(type_expr * t, char *id);static int check4constmem(type_expr * t);int EiC_S_LEVEL;static int NoPTR = 0;static eicstack_t breakstack = {0, NULL};static eicstack_t contstack = {0, NULL};static eicstack_t *casestack;static int BREAK = 0, CONT = 0, CASEON;#if 1void EiCp_freeLabels(Label_t *lab){ if(lab) { EiCp_freeLabels(lab->nxt); xfree(lab->name); xfree(lab); }}Label_t * EiCp_addLabel(Label_t *lab, char *name, int loc, int chck){ Label_t *nlab; if(chck) { /* check 4 duplicated labels */ nlab = lab; while(nlab) { if(strcmp(name, nlab->name) == 0) EiC_error("Duplicate label %s",name); nlab = nlab->nxt; } } nlab = xmalloc(sizeof(*nlab)); nlab->name = xmalloc(strlen(name)+1); strcpy(nlab->name,name); nlab->loc = loc; nlab->nxt = lab; return nlab;}#endif void addoffset(eicstack_t * S, int nxt, int offset){ unsigned i; val_t *v; for (i = nxt, v = &S->val[nxt]; i < S->n; ++v, ++i) v->ival += offset;}static void correctit(code_t * C, eicstack_t * S, int nxt, int loc){ val_t addr; if(!C->binst) return; while (S->n > nxt) { EiC_eicpop(S, &addr); C->inst[addr.ival].val.ival = loc-addr.ival; }}static int comppair(const void * p1,const void * p2){ return ((pair_t*)p1)->match.ival - ((pair_t*)p2)->match.ival;}void fixcasestack(token_t * e1, int nxt, int loc){ void qsort(void *base, size_t nm, size_t sz, int (*f)()); int i; if (casestack->n > 0) { correctit(&e1->Code, &breakstack, nxt, e1->Code.nextinst); if (casestack->val[0].ival == 0) casestack->val[0].ival = e1->Code.nextinst - loc; else casestack->val[0].ival -= loc; for (i = 2; i < casestack->n; i += 2) casestack->val[i].ival -= loc; qsort(&casestack->val[1], (casestack->n - 1) >> 1, sizeof(val_t) << 1, comppair); } else EiC_error("Illegal switch statement");}void EiC_initparser(){ extern int EiC_ErrorRecover; EiC_work_tab = stand_tab; EiC_ErrorRecover = 0;}void EiC_parse(environ_t * env){ void EiC_comm_switch(void); token_t e1; val_t v; int t; EiC_S_LEVEL = 1; EiC_inittoken(&e1); while ((t = EiC_lexan()) != DONE) { EiC_freetoken(&e1); if (t == ':') { /* get an EiC command */ int h; h = EiC_work_tab; EiC_work_tab = eic_tab; if (EiC_lexan() == ID) { if (EiC_gettype(token->Val.sym->type) == t_eic) (*token->Val.sym->val.func) (); else { EiC_remsym(token->Val.sym); EiC_error("Unknown EiC command"); } } else if(token->Tok == '-') EiC_comm_switch(); else EiC_error("Expected an EiC command"); EiC_work_tab = h; continue; } else if(t == '?') { printf("\t If you want help, enter :help\n\n"); continue; } retractlexan();#if 1 switch(t) { TYPEQUAL: STORECLASS: TYPESPEC: EiC_ext_decl(&e1); break; default: EiC_stmt(&e1); }#else block(&e1);#endif EiC_concode(&env->CODE, &e1.Code); } EiC_concode(&env->CODE, &e1.Code); if (e1.Type) v.p.p = EiC_copytype(e1.Type); else v.p.p = EiC_addtype(t_void, NULL); EiC_freetoken(&e1); EiC_generate(&env->CODE, halt, &v, 0);}/* * Globals used for * local aggregate data */unsigned int EiC_ASPOT = 0;static unsigned int MASPOT = 0, ADDLOCALS = 0; void EiC_updateLocals(void){ if (EiC_ASPOT > MASPOT) MASPOT = EiC_ASPOT; if (EiC_ENV->lsp > ADDLOCALS) ADDLOCALS = EiC_ENV->lsp;}static void addinlocals(token_t * e1,int n){ val_t v; token_t e2; EiC_inittoken(&e2); v.ival = n + (MASPOT>0); EiC_generate(&e2.Code, checkar, &v, 0); setCodeLineNo(&e2.Code,e2.Code.nextinst-1,0); if (MASPOT) { v.ival = MASPOT; EiC_generate(&e2.Code, pushint, &v, 0); setCodeLineNo(&e2.Code,e2.Code.nextinst-1,0); v.ival = n; { /* correct for AAA location */ int i, N; code_t *c = &e1->Code; N = nextinst(c); for(i = 0; i < N; ++i) if(opcode(c,i) == lda && ivalcode(c,i) == -1) ivalcode(c,i) = n; } EiC_generate(&e2.Code, massign, &v, 1); setCodeLineNo(&e2.Code,e2.Code.nextinst-1,0); EiC_generate(&e1->Code, fmem, &v, 1); setCodeLineNo(&e1->Code,e1->Code.nextinst-1,0); v.ival = n; } EiC_generate(&e1->Code, reducear, &v, 0); setCodeLineNo(&e1->Code,e1->Code.nextinst-1,0); EiC_concode(&e2.Code, &e1->Code); e1->Code = e2.Code; ADDLOCALS = EiC_ASPOT = MASPOT = 0;}static void block(token_t * e1){ token_t e2; EiC_inittoken(&e2); while(EiC_ext_decl(&e2)) { EiC_contoken(e1,&e2); EiC_inittoken(&e2); } while (EiC_lexan() != '}' && token->Tok != DONE) { retractlexan(); EiC_stmt(e1); } if (token->Tok == DONE) EiC_error("Expected }");}static void stmt1(token_t * e1){ void EiC_clearTempories(); int bp; unsigned aspot; switch (EiC_lexan()) { case '{': /* compound statement */ EiC_S_LEVEL++; bp = EiC_ENV->lsp; aspot = EiC_ASPOT; block(e1); EiC_updateLocals(); EiC_clearTempories(); EiC_ASPOT = aspot; EiC_reset_env_pointers(e1, bp); EiC_remlevel(EiC_S_LEVEL); EiC_S_LEVEL--; break; case casesym: case defaultsym: label_stmt(e1); break; case gotosym: case breaksym: case continuesym: case returnsym: jump_stmt(e1); break; case ifsym: case switchsym: select_stmt(e1); break; case whilesym: case dosym: case forsym: iter_stmt(e1); break; TYPEQUAL: STORECLASS: TYPESPEC: EiC_error("Unexpected declaration"); retractlexan(); EiC_ext_decl(e1); break;#if defined(ILOOKAHEAD) && (MAX_TOKENS > 1) case ID: /* handle label statements */ if(EiC_lexan() == ':') { extern int EiC_INFUNC; retractlexan(); if(!EiC_INFUNC) EiC_error("Misplaced label statement"); else { e1->Code.labels = EiCp_addLabel(e1->Code.labels, token->Val.sym->id, e1->Code.nextinst, 1); EiC_lexan(); } break; } else retractlexan();#endif default: retractlexan(); out_expr(e1); EiC_match(';', " ; "); return; } /* to get here a statement was executed, therefore */ e1->Type = EiC_addtype(t_void, e1->Type); EiC_clearTempories();}void EiC_stmt(token_t *e1){ static int Stmts = 0; Stmts++; stmt1(e1); Stmts--; if (EiC_S_LEVEL == 1 && Stmts == 0) { EiC_updateLocals(); if(ADDLOCALS > 0) addinlocals(e1,ADDLOCALS); }}static void label_stmt(token_t * e1){ if (!CASEON) { EiC_error("Illegal label"); return; } if (token->Tok == casesym) { token_t e2; int t; val_t v; EiC_inittoken(&e2); EiC_assign_expr(&e2); EiC_match(':', " :"); if (isconst(e2.Type)) { t = EiC_gettype(e2.Type); if (t >= t_char && t <= t_uint) { for (t = 1; t < casestack->n; t += 2) if (e2.Val.ival == casestack->val[t].ival) EiC_error("Duplicate case in switch"); EiC_eicpush(casestack, e2.Val); v.ival = e1->Code.nextinst; EiC_eicpush(casestack, v); } else EiC_error("Must be integer type"); } else EiC_error("Must be const_expr type"); EiC_stmt(e1); EiC_freetoken(&e2); } else { /* default */ if (casestack->val[0].ival != 0) EiC_error("Duplicate default in switch"); EiC_match(':', " :"); casestack->val[0].ival = e1->Code.nextinst; EiC_stmt(e1); }}static void select_stmt(token_t * e1){ int t; token_t e2; val_t u1; EiC_inittoken(&e2); if (token->Tok == ifsym) { EiC_match('(', " ( "); out_expr(&e2); testfortype(&e2,1); t = EiC_gettype(e2.Type); EiC_match(')', " ) "); EiC_contoken(e1, &e2); u1.ival = e1->Code.nextinst; genJump(e1,&u1,t,0); EiC_stmt(e1); if (EiC_lexan() == elsesym) { setInst(&e1->Code,u1.ival,val.ival,e1->Code.nextinst-u1.ival+1); u1.ival = e1->Code.nextinst; EiC_generate(&e1->Code, jmpu, &u1, 0); setCodeLineNo(&e1->Code,e1->Code.nextinst-1,0); EiC_stmt(e1); setInst(&e1->Code,u1.ival,val.ival,e1->Code.nextinst-u1.ival); } else { setInst(&e1->Code,u1.ival,val.ival,e1->Code.nextinst-u1.ival); retractlexan(); } } else {/* switchsym */ int nxtbreak, loc; eicstack_t *hold; BREAK++; CASEON++; nxtbreak = breakstack.n; EiC_match('(', " ("); out_expr(&e2); EiC_match(')', " )"); hold = casestack; casestack = (eicstack_t *) xcalloc(1, sizeof(eicstack_t)); u1.ival = 0; EiC_eicpush(casestack, u1); /* push dummy for default */ EiC_contoken(e1, &e2); u1.p.p = casestack; loc = e1->Code.nextinst; EiC_generate(&e1->Code, jmptab, &u1, 0); EiC_stmt(e1); fixcasestack(e1, nxtbreak, loc); casestack = hold; BREAK--; CASEON--; }}static void testfortype(token_t *e1, int NoVoid){ int t = EiC_gettype(e1->Type); if(!isArithmetic(t) && t != t_pointer) { if(t == t_void) { if(NoVoid) EiC_error("Void expression"); }else EiC_warningerror("Possible non relational operation"); }}static void genJump(token_t *e1, val_t *v, int t,int T){ /* 0 for false and 1 for True */ static int tab[2][5] = {{ jmpFint,jmpFlng,jmpFdbl,jmpFptr, jmpFllng}, { jmpTint,jmpTlng,jmpTdbl,jmpTptr, jmpTllng}}; switch(t) { default: EiC_error("Undefined type for relational operation"); case t_char: case t_uchar: case t_short:case t_ushort: case t_int: case t_uint: EiC_generate(&e1->Code, tab[T][0], v, 0); break; case t_long: case t_ulong: EiC_generate(&e1->Code, tab[T][1], v, 0); break; case t_float: case t_double: EiC_generate(&e1->Code, tab[T][2], v, 0); break; case t_pointer: EiC_generate(&e1->Code, tab[T][3], v, 0); break; case t_llong: EiC_generate(&e1->Code, tab[T][4], v, 0); break; }}static void iter_stmt(token_t * e1){ int t, rt,nxtbreak, nxtcont; val_t u1; token_t e2, e3; EiC_inittoken(&e2); BREAK++, CONT++; nxtbreak = breakstack.n; nxtcont = contstack.n; switch (token->Tok) { case dosym: u1.ival = e1->Code.nextinst; EiC_stmt(e1); if (EiC_lexan() != whilesym) EiC_error("Missing while in do while statement"); EiC_match('(', " ("); correctit(&e1->Code, &contstack, nxtcont, e1->Code.nextinst); out_expr(&e2); EiC_match(')', ")"); EiC_match(';', " ;"); testfortype(&e2,1); rt = EiC_gettype(e2.Type); EiC_contoken(e1, &e2); u1.ival = u1.ival - e1->Code.nextinst; genJump(e1,&u1,rt,1); /*EiC_generate(&e1->Code, jmpTint, &u1, 0);*/ correctit(&e1->Code, &breakstack, nxtbreak, e1->Code.nextinst); break; case whilesym: u1.ival = e1->Code.nextinst; EiC_generate(&e1->Code, jmpu, &u1, 0); setCodeLineNo(&e1->Code,e1->Code.nextinst-1,0); EiC_match('(', " ( "); out_expr(&e2); /* <expr> */ testfortype(&e2,1); rt = EiC_gettype(e2.Type); EiC_match(')', " ) "); EiC_stmt(e1); /* <stmt> */ setInst(&e1->Code,u1.ival,val.ival,e1->Code.nextinst-u1.ival); t = e1->Code.nextinst; EiC_contoken(e1, &e2); u1.ival -= e1->Code.nextinst - 1; genJump(e1,&u1,rt,1); /*EiC_generate(&e1->Code, jmpTint, &u1, 0);*/ setCodeLineNo(&e1->Code,e1->Code.nextinst-1,0); correctit(&e1->Code, &breakstack, nxtbreak, e1->Code.nextinst); correctit(&e1->Code, &contstack, nxtcont, t); break; case forsym: EiC_inittoken(&e3); EiC_match('(', " ( "); out_expr(e1); /* expr1 */ EiC_match(';', " ; "); u1.ival = e1->Code.nextinst; EiC_generate(&e1->Code, jmpu, &u1, 0); out_expr(&e2); /* expr2 */ testfortype(&e2,0); rt = EiC_gettype(e2.Type); EiC_match(';', " ; "); out_expr(&e3); /* expr3 */ EiC_match(')', " ; "); EiC_stmt(e1); correctit(&e1->Code, &contstack, nxtcont, e1->Code.nextinst); EiC_contoken(e1, &e3); setInst(&e1->Code,u1.ival,val.ival,e1->Code.nextinst-u1.ival); EiC_contoken(e1, &e2); u1.ival -= (e1->Code.nextinst - 1); if (rt == t_void) EiC_generate(&e1->Code, jmpu, &u1, 0); else genJump(e1,&u1,rt,1); /*EiC_generate(&e1->Code, jmpTint, &u1, 0);*/ setCodeLineNo(&e1->Code,e1->Code.nextinst -1, 0); correctit(&e1->Code, &breakstack, nxtbreak, e1->Code.nextinst); break; } BREAK--, CONT--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -