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

📄 expr.c

📁 编译原理这门课确实不是很容易
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * 68K/386 32-bit C compiler.
 *
 * copyright (c) 1997, David Lindauer
 * 
 * This compiler is intended for educational use.  It may not be used
 * for profit without the express written consent of the author.
 *
 * It may be freely redistributed, as long as this notice remains intact
 * and either the original sources or derived sources 
 * are distributed along with any executables derived from the originals.
 *
 * The author is not responsible for any damages that may arise from use
 * of this software, either idirect or consequential.
 *
 * v1.35 March 1997
 * David Lindauer, gclind01@starbase.spd.louisville.edu
 *
 * Credits to Mathew Brandt for original K&R C compiler
 *
 */
/*
 * Evaluate expressions very recursive descent.  MAke sure your STACK
 * is large enough to parse the expressions you want to parse.  a 4K stack
 * will handle all but the very extreme cases
 */
#include        <stdio.h>
#include        "expr.h"
#include        "c.h"
#include        "errors.h"
#include				"list.h"

extern int block_nesting;
extern int global_flag;
extern enum e_sym lastst;
extern char lastid[],laststr[];
extern TABLE gsyms,lsyms;
extern long ival;
extern long double rval;
/* Default types */
extern TYP stdint,stdlongdouble, stduns,stdstring;
TYP             stdfloat = { bt_float, 0, UF_DEFINED | UF_USED,0, 0,-1, -1, 8, {0, 0}, 0, 0,0 };
TYP             stddouble = { bt_double, 0, 0,0,0, -1, -1, 8, {0, 0}, 0, 0,0 };
TYP             stdvoid = { bt_matchall, 0, 0 ,0, 0,-1, -1, 4, {0, 0}, 0, 0,0 };
TYP             stdmatch = { bt_matchall, 0, UF_DEFINED | UF_USED,0, 0,-1, -1, 4, {0, 0}, &stdvoid, 0,0 };
TYP             stdlong = {bt_long, 0, 0,0,0,-1, -1, 4, {0, 0}, 0, 0,0 };
TYP             stdunsigned = {bt_unsigned, 0, 0,0,0,-1, -1, 4, {0, 0}, 0, 0,0 };
TYP             stdchar = {bt_char, 0, 0,0,0,-1, -1, 1, {0, 0}, 0, 0,0 };
TYP             stdfunc = {bt_func, 1, UF_DEFINED | UF_USED,0,0,-1, -1, 0, {0, 0}, &stdint, 0,0};
extern TYP      *head;          /* shared with decl */
extern TABLE    tagtable;
extern char declid[100];
extern int goodcode;
extern int prm_cplusplus;
extern int regdsize,regasize,regfsize,stackadd,stackmod;

int skm_closepa[] = { closepa, comma, semicolon, end, 0 };
int skm_closebr[] = { closebr, comma, openbr, semicolon, end, 0 };
static SYM *lastsym;
static int globaldref = 0;
static char regname[] = "processor reg" ;
static char *nm = 0;
static TYP *asntyp = 0;
static int dumpos;
static SYM undef;
void exprini(void)
{
	globaldref = 0;
	asntyp = 0;
	dumpos = 0;
	undef.value.i = 0;
	undef.name = "UNDEFINED";
}
ENODE    *makenode(enum e_node nt, char *v1, char *v2)
/*
 *      build an expression node with a node type of nt and values
 *      v1 and v2.
 */
{       ENODE    *ep;
        ep = xalloc(sizeof(ENODE));
        ep->nodetype = (char)nt;
				ep->cflags = 0;
        ep->v.p[0] = v1;
        ep->v.p[1] = v2;
        return ep;
}

TYP *deref(ENODE **node, TYP *tp)
/*
 *      build the proper dereference operation for a node using the
 *      type pointer tp.
 */
{
				ENODE *onode = *node;
				switch( tp->type ) {
								case bt_double:
                        *node = makenode(en_doubleref,*node,0);
                        break;
								case bt_longdouble:
                        *node = makenode(en_longdoubleref,*node,0);
                        break;
								case bt_float:
                        *node = makenode(en_floatref,*node,0);
                        break;
								case bt_unsignedchar:
                        *node = makenode(en_ub_ref,*node,0);
                        break;
								case bt_unsignedshort:
                        *node = makenode(en_uw_ref,*node,0);
                        break;
                case bt_char:
                        *node = makenode(en_b_ref,*node,0);
                        break;
                case bt_short:
                case bt_enum:
                        *node = makenode(en_w_ref,*node,0);
                        break;
                case bt_unsigned:
                        *node = makenode(en_ul_ref,*node,0);
												break;
                case bt_long:
                case bt_matchall:
                case bt_pointer:
								case bt_ptrfunc:
								case bt_ref:
                        *node = makenode(en_l_ref,*node,0);
                        break;
                default:
                        generror(ERR_DEREF,0,0);
                        break;
                }
				(*node)->cflags = onode->cflags;
        return tp;
}
ENODE *dummyvar(int size, TYP *type)
{
	char nm[20];
	ENODE *newnode;
	SYM *sp = xalloc(sizeof(SYM));
	sprintf(nm,"**DUMMY%d",dumpos++);
	sp->name = litlate(nm);
	sp->defalt = 0;
  sp->storage_class = sc_auto;
  sp->tp = type;
	type->uflags |= UF_USED;
	sp->extflag = FALSE;
	sp->absflag = FALSE;
	sp->intflag = FALSE;
	sp->pascaldefn = FALSE;
	sp->init = 0;
	sp->indecltable = 0;
	sp->funcparm = 0;
	sp->inreg = 0;
	sp->staticlabel = FALSE;
	sp->value.i = block_nesting;
	insert(sp,&lsyms);
	newnode = makenode(en_autocon,sp,0);
	return newnode;
}
int isintconst(int type)
{
	switch (type) {
		case en_icon:
		case en_lcon:
		case en_lucon:
		case en_iucon:
		case en_ccon:
			return 1;
	}
	return 0;
}
TYP     *nameref(ENODE **node)
/*
 * get an identifier.  If it is followed by parenthesis gather the
 * function parms.  If it is an undefined function declare it as external
 * for now.
 */
{       SYM             *sp;
        TYP             *tp,*tp1;
				ENODE *pnode=0,*qnode = 0;
				int fn = FALSE;
				char buf[100];
				strcpy(buf,lastid);
				getsym();
/* Get function args */
				if (lastst == openpa) {
					fn = TRUE;
					getsym();
					tp1 = gatherparms(&pnode);
					sp = funcovermatch(buf,tp1);
					if (sp)
						tp1->sname = nm = sp->name;
					else
#ifdef CPLUSPLUS
						if (prm_cplusplus)
							tp1->sname = nm = cppmangle(buf,tp1);
						else
#endif
							tp1->sname = nm = litlate(buf);
				}
				else {
					nm = litlate(buf);
					sp = gsearch(nm);
				}
        if( sp == 0 ) {
/* No such identifier */
                if (fn) {
/* External function, put it in the symbol table */
#ifdef CPLUSPLUS
												if (prm_cplusplus) 
													gensymerror(ERR_NOFUNCMATCH,nm);
												else
#endif
													gensymerror(ERR_NOPROTO,nm);
                        ++global_flag;
												sp = xalloc(sizeof(SYM));
                				sp->name = litlate(nm);
												sp->tp = maketype(bt_func,0);
												*(sp->tp) = stdfunc;
                        sp->storage_class = sc_externalfunc;
												sp->extflag = TRUE;
                        insert(sp,&gsyms);
                        --global_flag;
                        *node = makenode(en_napccon,sp,0);
												parmlist(&pnode,tp1,0);
												*node = makenode(en_void,*node,pnode);
                        tp = &stdint;
												qnode = makenode(en_icon,(char *)-4,0);
	                      *node = makenode(en_fcall,qnode,*node);
												goodcode |= GF_ASSIGN;
                        }
                else    {
/* External non-function.  These also get put in the symbol table so that
 * we don't keep spitting errors out but also put an error out
 */
#ifdef CPLUSPLUS
												if (prm_cplusplus && asntyp && asntyp->type == bt_ptrfunc) {
													sp = funcovermatch(lastid,asntyp);
													if (sp)
														goto foundsp;
												}
#endif
												sp = xalloc(sizeof(SYM));
                				sp->name = nm;
                        sp->tp = tp = &stdmatch;
												sp->storage_class = sc_external;
												insert(sp,&lsyms);
												*node = makenode(en_nacon,&undef,0);
												gensymerror(ERR_UNDEFINED,nm);
                        tp = deref(node,tp);
                        }
                }
        else    {
/* If we get here the symbol was already in the table
 */
foundsp:
								sp->tp->uflags |= UF_USED;
                if( (tp = sp->tp) == 0 ) {
/* This lack of type info should never happen */
                        tp = &stdmatch;
												*node = makenode(en_nacon,&undef,0);
												gensymerror(ERR_UNDEFINED,nm);
                        tp = deref(node,tp);
                        return tp;       /* guard against untyped entries */
                        }
                switch( sp->storage_class ) {
                        case sc_static:
                        case sc_global:
                        case sc_external:
                        case sc_externalfunc:
												case sc_abs:
																sp->extflag = TRUE;
																if (fn) {
/* make a function node */
																	if (sp->tp->type == bt_ptrfunc)
                                		*node = makenode(en_nacon,sp,0);
																	else
                                		*node = makenode(en_napccon,sp,0);
isfunc:
																	if (sp->tp->type != bt_ptrfunc && sp->tp->type != bt_func && sp->tp->type != bt_ifunc)
																		generror(ERR_MISMATCH,0,0);
																	if (sp->tp->type == bt_ptrfunc)
																		tp = deref(node,tp);
#ifdef CPLUSPLUS
																	if (prm_cplusplus && !strcmp(buf,"main"))
																		generror(ERR_NOMAIN,0,0);
#endif
																	parmlist(&pnode,tp1,sp->tp);
																	*node = makenode(en_void,*node,pnode);
																	qnode = makenode(en_icon,(char *)sp->tp->btp->size,0);
                                  tp = tp->btp;
																	if (sp->intflag)
	                                	*node = makenode(en_intcall,qnode,*node);
																	else
																	if (tp->type == bt_union || tp->type == bt_struct) {
																		if (sp->pascaldefn)
	                              		  *node = makenode(en_pfcallb,qnode,*node);
																		else 
	                              		  *node = makenode(en_fcallb,qnode,*node);
																		(*node)->size = tp->size;
																	}
																	else
																		if (sp->pascaldefn)
	                              			*node = makenode(en_pfcall,qnode,*node);
																		else
	                              			*node = makenode(en_fcall,qnode,*node);
																	if (tp)
																		(*node)->cflags = tp->cflags;
																	goodcode |= GF_ASSIGN;
																}
																else
/* otherwise make a node for a regular variable */
																	if (sp->absflag)
                                		*node = makenode(en_absacon,sp,0);
																	else
																		if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc) {
																			fn = TRUE;
                                			*node = makenode(en_napccon,sp,0);
																		}
																		else
																			if (sp->staticlabel)
																				*node = makenode(en_nalabcon,(char *)sp->value.i,0);
																			else
                                				*node = makenode(en_nacon,sp,0);
                                break;
                        case sc_const:
/* constants and enums */
                                *node = makenode(en_icon,(char *)sp->value.i,0);
																return &stdint;
                        default:        /* auto and any errors */
                                if( sp->storage_class != sc_auto && sp->storage_class != sc_autoreg) {
                                        gensymerror(ERR_ILLCLASS2,sp->name);
																				tp = 0;
																}
																else {
/* auto variables */
															 		if (sp->storage_class == sc_auto)
                                		*node = makenode(en_autocon,sp,0);
																	else if (sp->storage_class == sc_autoreg)
                                		*node = makenode(en_autoreg,sp,0);
																	if (fn)
																		goto isfunc;
																}
                                break;
                        }
/* dereference if it isn't an array or structure address */

								(*node)->cflags = tp->cflags;
								/* deref if not an array or if is function parm */
	              if(!fn && tp && (tp->val_flag == 0 || (sp->funcparm && tp->type == bt_pointer)))
  	                     tp = deref(node,tp);
/* and dereference again if it is a refernece variable */
								if (tp->type == bt_ref) {
												tp = tp->btp;
												tp = deref(node,tp);
								}
												
                }
				lastsym = sp;
        return tp;
}

void promote_type(TYP *typ, ENODE **node)
/*
 * Type promotion for casts and function args 
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -