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

📄 codegen.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		clearlabel(&label1);		addoplabel(OP_JUMP, &label1);		setlabel(nextcaselabel);		clearlabel(nextcaselabel);		(void) getexprlist();		if (gettoken() != T_COLON) {			scanerror(T_SEMICOLON, "Colon expected after CASE expression");			return;		}		addoplabel(OP_CASEJUMP, nextcaselabel);		setlabel(&label1);		getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);		return;	case T_DEFAULT:		if (gettoken() != T_COLON) {			scanerror(T_SEMICOLON, "Colon expected after DEFAULT keyword");			return;		}		if (defaultlabel == NULL_LABEL) {			scanerror(T_SEMICOLON, "DEFAULT not within SWITCH statement");			return;		}		if (defaultlabel->l_offset > 0) {			scanerror(T_SEMICOLON, "Multiple DEFAULT clauses in SWITCH");			return;		}		clearlabel(&label1);		addoplabel(OP_JUMP, &label1);		setlabel(defaultlabel);		addop(OP_POP);		setlabel(&label1);		getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);		return;	case T_ELSE:		scanerror(T_SEMICOLON, "ELSE without preceeding IF");		return;	case T_MAT:		getmatdeclaration(SYM_UNDEFINED);		break;	case T_OBJ:		getobjdeclaration(SYM_UNDEFINED);		break;	case T_PRINT:		printeol = TRUE;		for (;;) {			switch (gettoken()) {				case T_RIGHTBRACE:				case T_NEWLINE:					rescantoken();					/*FALLTHRU*/				case T_SEMICOLON:					if (printeol)						addop(OP_PRINTEOL);					return;				case T_COLON:					printeol = FALSE;					break;				case T_COMMA:					printeol = TRUE;					addop(OP_PRINTSPACE);					break;				case T_STRING:					printeol = TRUE;					addopptr(OP_PRINTSTRING, tokenstring());					break;				default:					printeol = TRUE;					rescantoken();					(void) getassignment();					addopone(OP_PRINT, (long) PRINT_NORMAL);			}		}	case T_QUIT:		switch (gettoken()) {			case T_STRING:				addopptr(OP_QUIT, tokenstring());				break;			default:				addopptr(OP_QUIT, NULL);				rescantoken();		}		break;	case T_SYMBOL:		if (nextchar() == ':') {	/****HACK HACK ****/			definelabel(tokenstring());			getstatement(contlabel, breaklabel, 				NULL_LABEL, NULL_LABEL);			return;		}		reread();		/* fall into default case */	default:		rescantoken();		type = getexprlist();		if (contlabel || breaklabel || (curfunc->f_name[0] != '*')) {			addop(OP_POP);			break;		}		addop(OP_SAVE);		if (isassign(type) || (curfunc->f_name[1] != '\0')) {			addop(OP_POP);			break;		}		addop(OP_PRINTRESULT);		break;	}	switch (gettoken()) {		case T_RIGHTBRACE:		case T_NEWLINE:		case T_EOF:			rescantoken();			break;		case T_SEMICOLON:			break;		default:			scanerror(T_SEMICOLON, "Semicolon expected");			break;	}}/* * Read in an object declaration. * This is of the following form: *	OBJ type [ '{' id [ ',' id ] ... '}' ]  [ objlist ]. * The OBJ keyword has already been read.  Symtype is SYM_UNDEFINED if this * is an OBJ statement, otherwise this is part of a declaration which will * define new symbols with the specified type. */static voidgetobjdeclaration(symtype)	int symtype;{	char *name;			/* name of object type */	int count;			/* number of elements */	int index;			/* current index */	int i;				/* loop counter */	BOOL err;			/* error flag */	int indices[MAXINDICES];	/* indices for elements */	err = FALSE;	if (gettoken() != T_SYMBOL) {		scanerror(T_SEMICOLON, "Object type name missing");		return;	}	name = addliteral(tokenstring());	if (gettoken() != T_LEFTBRACE) {		rescantoken();		getobjvars(name, symtype);		return;	}	/*	 * Read in the definition of the elements of the object.	 */	count = 0;	for (;;) {		if (gettoken() != T_SYMBOL) {			scanerror(T_SEMICOLON, "Missing element name in OBJ statement");			return;		}		index = addelement(tokenstring());		for (i = 0; i < count; i++) {			if (indices[i] == index) {				scanerror(T_NULL, "Duplicate element name \"%s\"", tokenstring());				err = TRUE;				break;			}		}		indices[count++] = index;		switch (gettoken()) {			case T_RIGHTBRACE:				if (!err)					(void) defineobject(name, indices, count);				switch (gettoken()) {					case T_SEMICOLON:					case T_NEWLINE:						rescantoken();						return;				}				rescantoken();				getobjvars(name, symtype);				return;			case T_COMMA:			case T_SEMICOLON:			case T_NEWLINE:				break;			default:				scanerror(T_SEMICOLON, "Bad object element definition");				return;		}	}}/* * Routine to collect a set of variables for the specified object type * and initialize them as being that type of object. * Here *	objlist = name initlist [ ',' name initlist ] ... ';'. * If symtype is SYM_UNDEFINED, then this is an OBJ statement where the * values can be any variable expression, and no symbols are to be defined. * Otherwise this is part of a declaration, and the variables must be raw * symbol names which are defined with the specified symbol type. */static voidgetobjvars(name, symtype)	int symtype;	char *name;		/* object name */{	long index;		/* index for object */	char *symname;	index = checkobject(name);	if (index < 0) {		scanerror(T_SEMICOLON, "Object %s has not been defined yet", name);		return;	}	for (;;) {		if (symtype == SYM_UNDEFINED)			(void) getidexpr(TRUE, TRUE);		else {			if (gettoken() != T_SYMBOL) {				scanerror(T_SEMICOLON, "Missing object variable name");				return;			}			symname = tokenstring();			definesymbol(symname, symtype);			usesymbol(symname, FALSE);		}		addopone(OP_OBJCREATE, index);		(void) getinitlist();		switch (gettoken()) {			case T_COMMA:				break;			case T_SEMICOLON:			case T_NEWLINE:				rescantoken();				return;			default:				scanerror(T_SEMICOLON, "Bad OBJ statement");				return;		}	}}/* * Read a matrix definition declaration for a one or more dimensional matrix. * The MAT keyword has already been read.  This also handles an optional * matrix initialization list enclosed in braces.  Symtype is SYM_UNDEFINED * if this is part of a MAT statement which handles any variable expression. * Otherwise this is part of a declaration and only a symbol name is allowed. */static voidgetmatdeclaration(symtype)	int symtype;{	long dim;	long index;	long count;	long patchpc;	char *name;	if (symtype == SYM_UNDEFINED)		(void) getidexpr(FALSE, TRUE);	else {		if (gettoken() != T_SYMBOL) {			scanerror(T_COMMA, "Missing matrix variable name");			return;		}		name = tokenstring();		definesymbol(name, symtype);		usesymbol(name, FALSE);	}	if (gettoken() != T_LEFTBRACKET) {		scanerror(T_SEMICOLON, "Missing left bracket for MAT");		return;	}	dim = 1;	/*	 * If there are no bounds given for the matrix, then they must be	 * implicitly defined by a list of initialization values.  Put in	 * a dummy number in the opcode stream for the bounds and remember	 * its location.  After we know how many values are in the list, we	 * will patch the correct value back into the opcode.	 */	if (gettoken() == T_RIGHTBRACKET) {		clearopt();		patchpc = curfunc->f_opcodecount + 1;		addopone(OP_NUMBER, (long) -1);		clearopt();		addop(OP_ZERO);		addopone(OP_MATCREATE, dim);		count = getinitlist();		if (count == 0) {			scanerror(T_NULL, "Initialization required for implicit matrix bounds");			return;		}		index = addqconstant(itoq(count - 1));		if (index < 0)			math_error("Cannot allocate constant");		curfunc->f_opcodes[patchpc] = index;		return;	}	/*	 * This isn't implicit, so we expect expressions for the bounds.	 */	rescantoken();	while (TRUE) {		(void) getassignment();		switch (gettoken()) {			case T_RIGHTBRACKET:			case T_COMMA:				rescantoken();				addop(OP_ONE);				addop(OP_SUB);				addop(OP_ZERO);				break;			case T_COLON:				(void) getassignment();				break;			default:				rescantoken();		}		switch (gettoken()) {			case T_RIGHTBRACKET:				if (gettoken() != T_LEFTBRACKET) {					rescantoken();					addopone(OP_MATCREATE, dim);					(void) getinitlist();					return;				}				/* proceed into comma case */				/*FALLTHRU*/			case T_COMMA:				if (++dim <= MAXDIM)					break;				scanerror(T_SEMICOLON, "Only %ld dimensions allowed", MAXDIM);				return;			default:				scanerror(T_SEMICOLON, "Illegal matrix definition");				return;		}	}}/* * Get an optional initialization list for a matrix or object definition. * Returns the number of elements that are in the list, or -1 on parse error. * This assumes that the address of a matrix or object variable is on the * stack, and so this routine will pop it off when complete. *	initlist = [ '=' '{' assignment [ ',' assignment ] ... '}' ]. */static longgetinitlist(){	long index;	int oldmode;	if (gettoken() != T_ASSIGN) {		rescantoken();		addop(OP_POP);		return 0;	}	oldmode = tokenmode(TM_DEFAULT);	if (gettoken() != T_LEFTBRACE) {		scanerror(T_SEMICOLON, "Missing brace for initialization list");		(void) tokenmode(oldmode);		return -1;	}	for (index = 0; ; index++) {		getassignment();		addopone(OP_ELEMINIT, index);		switch (gettoken()) {			case T_COMMA:				continue;			case T_RIGHTBRACE:				(void) tokenmode(oldmode);				addop(OP_POP);				return index + 1;			default:				scanerror(T_SEMICOLON, "Bad initialization list");				(void) tokenmode(oldmode);				return -1;		}	}}/* * Get a condition. * condition = '(' assignment ')'. */static voidgetcondition(){	if (gettoken() != T_LEFTPAREN) {		scanerror(T_SEMICOLON, "Missing left parenthesis for condition");		return;	}	(void) getexprlist();	if (gettoken() != T_RIGHTPAREN) {		scanerror(T_SEMICOLON, "Missing right parenthesis for condition");		return;	}}/* * Get an expression list consisting of one or more expressions, * separated by commas.  The value of the list is that of the final expression. * This is the top level routine for parsing expressions. * Returns flags describing the type of assignment or expression found. * exprlist = assignment [ ',' assignment ] ... */static intgetexprlist(){	int	type;	type = getassignment();	while (gettoken() == T_COMMA) {		addop(OP_POP);		(void) getassignment();		type = EXPR_RVALUE;	}	rescantoken();	return type;}/* * Get an assignment (or possibly just an expression). * Returns flags describing the type of assignment or expression found. * assignment = lvalue '=' assignment *	| lvalue '+=' assignment *	| lvalue '-=' assignment *	| lvalue '*=' assignment *	| lvalue '/=' assignment *	| lvalue '%=' assignment *	| lvalue '//=' assignment *	| lvalue '&=' assignment *	| lvalue '|=' assignment *	| lvalue '<<=' assignment *	| lvalue '>>=' assignment *	| lvalue '^=' assignment *	| lvalue '**=' assignment *	| orcond. */static intgetassignment(){	int type;		/* type of expression */	long op;		/* opcode to generate */	type = getaltcond();	switch (gettoken()) {		case T_ASSIGN:		op = 0; break;		case T_PLUSEQUALS:	op = OP_ADD; break;		case T_MINUSEQUALS:	op = OP_SUB; break;		case T_MULTEQUALS:	op = OP_MUL; break;		case T_DIVEQUALS:	op = OP_DIV; break;		case T_SLASHSLASHEQUALS: op = OP_QUO; break;		case T_MODEQUALS:	op = OP_MOD; break;		case T_ANDEQUALS:	op = OP_AND; break;		case T_OREQUALS:	op = OP_OR; break;		case T_LSHIFTEQUALS: 	op = OP_LEFTSHIFT; break;		case T_RSHIFTEQUALS: 	op = OP_RIGHTSHIFT; break;		case T_POWEREQUALS:	op = OP_POWER; break;		case T_NUMBER:		case T_IMAGINARY:		case T_STRING:		case T_SYMBOL:		case T_OLDVALUE:		case T_LEFTPAREN:		case T_PLUSPLUS:		case T_MINUSMINUS:		case T_NOT:			scanerror(T_NULL, "Missing operator");			return type;		default:			rescantoken();			return type;	}	if (isrvalue(type)) {		scanerror(T_NULL, "Illegal assignment");		(void) getassignment();		return (EXPR_RVALUE | EXPR_ASSIGN);	}	writeindexop();	if (op)		addop(OP_DUPLICATE);	(void) getassignment();	if (op) {		addop(op);	}	addop(OP_ASSIGN);	return (EXPR_RVALUE | EXPR_ASSIGN);}/* * Get a possible conditional result expression (question mark). * Flags are returned indicating the type of expression found. * altcond = orcond [ '?' orcond ':' altcond ]. */static intgetaltcond(){	int type;		/* type of expression */	LABEL donelab;		/* label for done */	LABEL altlab;		/* label for alternate expression */	type = getorcond();	if (gettoken() != T_QUESTIONMARK) {		rescantoken();		return type;	}	clearlabel(&donelab);	clearlabel(&altlab);	addoplabel(OP_JUMPEQ, &altlab);	(void) getorcond();	if (gettoken() != T_COLON) {		scanerror(T_SEMICOLON, "Missing colon for conditional expression");		return EXPR_RVALUE;	}	addoplabel(OP_JUMP, &donelab);	setlabel(&altlab);	(void) getaltcond();	setlabel(&donelab);	return EXPR_RVALUE;}/* * Get a possible conditional or expression. * Flags are returned indicating the type of expression found. * orcond = andcond [ '||' andcond ] ... */static intgetorcond(){	int type;		/* type of expression */	LABEL donelab;		/* label for done */	clearlabel(&donelab);	type = getandcond();	while (gettoken() == T_OROR) {		addoplabel(OP_CONDORJUMP, &donelab);		(void) getandcond();		type = EXPR_RVALUE;	}	rescantoken();	if (donelab.l_chain > 0)		setlabel(&donelab);	return type;}/* * Get a possible conditional and expression. * Flags are returned indicating the type of expression found. * andcond = relation [ '&&' relation ] ... */static intgetandcond(){	int type;		/* type of expression */	LABEL donelab;		/* label for done */	clearlabel(&donelab);	type = getrelation();	while (gettoken() == T_ANDAND) {		addoplabel(OP_CONDANDJUMP, &donelab);		(void) getrelation();		type = EXPR_RVALUE;	}	rescantoken();	if (donelab.l_chain > 0)		setlabel(&donelab);	return type;}/* * Get a possible relation (equality or inequality), or just an expression. * Flags are returned indicating the type of relation found. * relation = sum '==' sum *	| sum '!=' sum *	| sum '<=' sum *	| sum '>=' sum *	| sum '<' sum *	| sum '>' sum *	| sum. */static intgetrelation(){	int type;		/* type of expression */	long op;		/* opcode to generate */	type = getsum();	switch (gettoken()) {		case T_EQ: op = OP_EQ; break;		case T_NE: op = OP_NE; break;		case T_LT: op = OP_LT; break;		case T_GT: op = OP_GT; break;		case T_LE: op = OP_LE; break;		case T_GE: op = OP_GE; break;		default:			rescantoken();			return type;	}	(void) getsum();	addop(op);	return EXPR_RVALUE;}/* * Get an expression made up of sums of products. * Flags indicating the type of expression found are returned. * sum = product [ {'+' | '-'} product ] ... */static intgetsum(){

⌨️ 快捷键说明

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