📄 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 1
void 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 + -