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

📄 parser.c

📁 微软的基于HMM的人脸识别原代码, 非常经典的说
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -