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

📄 codegen.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	int type;		/* type of expression found */	long op;		/* opcode to generate */	type = getproduct();	for (;;) {		switch (gettoken()) {			case T_PLUS:	op = OP_ADD; break;			case T_MINUS:	op = OP_SUB; break;			default:				rescantoken();				return type;		}		(void) getproduct();		addop(op);		type = EXPR_RVALUE;	}}/* * Get the product of arithmetic or expressions. * Flags indicating the type of expression found are returned. * product = orexpr [ {'*' | '/' | '//' | '%'} orexpr ] ... */static intgetproduct(){	int type;		/* type of value found */	long op;		/* opcode to generate */	type = getorexpr();	for (;;) {		switch (gettoken()) {			case T_MULT:	op = OP_MUL; break;			case T_DIV:	op = OP_DIV; break;			case T_MOD:	op = OP_MOD; break;			case T_SLASHSLASH: op = OP_QUO; break;			default:				rescantoken();				return type;		}		(void) getorexpr();		addop(op);		type = EXPR_RVALUE;	}}/* * Get an expression made up of arithmetic or operators. * Flags indicating the type of expression found are returned. * orexpr = andexpr [ '|' andexpr ] ... */static intgetorexpr(){	int type;		/* type of value found */	type = getandexpr();	while (gettoken() == T_OR) {		(void) getandexpr();		addop(OP_OR);		type = EXPR_RVALUE;	}	rescantoken();	return type;}/* * Get an expression made up of arithmetic and operators. * Flags indicating the type of expression found are returned. * andexpr = shiftexpr [ '&' shiftexpr ] ... */static intgetandexpr(){	int type;		/* type of value found */	type = getshiftexpr();	while (gettoken() == T_AND) {		(void) getshiftexpr();		addop(OP_AND);		type = EXPR_RVALUE;	}	rescantoken();	return type;}/* * Get a shift or power expression. * Flags indicating the type of expression found are returned. * shift = term '^' shiftexpr *	 | term '<<' shiftexpr *	 | term '>>' shiftexpr *	 | term. */static intgetshiftexpr(){	int type;		/* type of value found */	long op;		/* opcode to generate */	type = getterm();	switch (gettoken()) {		case T_POWER:		op = OP_POWER; break;		case T_LEFTSHIFT:	op = OP_LEFTSHIFT; break;		case T_RIGHTSHIFT: 	op = OP_RIGHTSHIFT; break;		default:			rescantoken();			return type;	}	(void) getshiftexpr();	addop(op);	return EXPR_RVALUE;}/* * Get a single term. * Flags indicating the type of value found are returned. * term = lvalue *	| lvalue '[' assignment ']' *	| lvalue '++' *	| lvalue '--' *	| '++' lvalue *	| '--' lvalue *	| real_number *	| imaginary_number *	| '.' *	| string *	| '(' assignment ')' *	| function [ '(' [assignment  [',' assignment] ] ')' ] *	| '!' term *	| '+' term *	| '-' term. */static intgetterm(){	int type;		/* type of term found */	type = gettoken();	switch (type) {		case T_NUMBER:			addopone(OP_NUMBER, tokennumber());			type = (EXPR_RVALUE | EXPR_CONST);			break;		case T_IMAGINARY:			addopone(OP_IMAGINARY, tokennumber());			type = (EXPR_RVALUE | EXPR_CONST);			break;		case T_OLDVALUE:			addop(OP_OLDVALUE);			type = 0;			break;		case T_STRING:			addopptr(OP_STRING, tokenstring());			type = (EXPR_RVALUE | EXPR_CONST);			break;		case T_PLUSPLUS:			if (isrvalue(getterm()))				scanerror(T_NULL, "Bad ++ usage");			writeindexop();			addop(OP_PREINC);			type = (EXPR_RVALUE | EXPR_ASSIGN);			break;		case T_MINUSMINUS:			if (isrvalue(getterm()))				scanerror(T_NULL, "Bad -- usage");			writeindexop();			addop(OP_PREDEC);			type = (EXPR_RVALUE | EXPR_ASSIGN);			break;		case T_NOT:			(void) getterm();			addop(OP_NOT);			type = EXPR_RVALUE;			break;		case T_MINUS:			(void) getterm();			addop(OP_NEGATE);			type = EXPR_RVALUE;			break;		case T_PLUS:			(void) getterm();			type = EXPR_RVALUE;			break;		case T_LEFTPAREN:			type = getexprlist();			if (gettoken() != T_RIGHTPAREN)				scanerror(T_SEMICOLON, "Missing right parenthesis");			break;		case T_SYMBOL:			rescantoken();			type = getidexpr(TRUE, FALSE);			break;		case T_LEFTBRACKET:			scanerror(T_NULL, "Bad index usage");			type = 0;			break;		case T_PERIOD:			scanerror(T_NULL, "Bad element reference");			type = 0;			break;		default:			if (iskeyword(type)) {				scanerror(T_NULL, "Expression contains reserved keyword");				type = 0;				break;			}			rescantoken();			scanerror(T_NULL, "Missing expression");			type = 0;	}	switch (gettoken()) {		case T_PLUSPLUS:			if (isrvalue(type))				scanerror(T_NULL, "Bad ++ usage");			writeindexop();			addop(OP_POSTINC);			return (EXPR_RVALUE | EXPR_ASSIGN);		case T_MINUSMINUS:			if (isrvalue(type))				scanerror(T_NULL, "Bad -- usage");			writeindexop();			addop(OP_POSTDEC);			return (EXPR_RVALUE | EXPR_ASSIGN);		default:			rescantoken();			return type;	}}/* * Read in an identifier expressions. * This is a symbol name followed by parenthesis, or by square brackets or * element refernces.  The symbol can be a global or a local variable name. * Returns the type of expression found. */static intgetidexpr(okmat, autodef)	BOOL okmat, autodef;{	int type;	char name[SYMBOLSIZE+1];	/* symbol name */	type = 0;	if (!getid(name))		return type;	switch (gettoken()) {		case T_LEFTPAREN:			getcallargs(name);			type = EXPR_RVALUE;			break;		case T_ASSIGN:			autodef = TRUE;			/* fall into default case */		default:			rescantoken();			usesymbol(name, autodef);	}	/*	 * Now collect as many element references and matrix index operations	 * as there are following the id.	 */	for (;;) {		switch (gettoken()) {			case T_LEFTBRACKET:				rescantoken();				if (!okmat)					return type;				getmatargs();				type = 0;				break;			case T_PERIOD:				getelement();				type = 0;				break;			case T_LEFTPAREN:				scanerror(T_NULL, "Function calls not allowed as expressions");			default:				rescantoken();				return type;		}	}}/* * Read in a filename for a read or write command. * Both quoted and unquoted filenames are handled here. * The name must be terminated by an end of line or semicolon. * Returns TRUE if the filename was successfully parsed. */static BOOLgetfilename(name, msg_ok, once)	char name[PATHSIZE+1];	BOOL msg_ok;		/* TRUE => ok to print error messages */	BOOL *once;		/* non-NULL => set to TRUE of -once read */{	/* look at the next token */	(void) tokenmode(TM_NEWLINES | TM_ALLSYMS);	switch (gettoken()) {		case T_STRING:		case T_SYMBOL:			break;		default:			if (msg_ok)				scanerror(T_SEMICOLON, "Filename expected");			return FALSE;	}	strcpy(name, tokenstring());	/* determine if we care about a possible -once option */	if (once != NULL) {		/* we care about a possible -once option */		if (strcmp(name, "-once") == 0) {			/* -once option found */			*once = TRUE;			/* look for the filename */			switch (gettoken()) {				case T_STRING:				case T_SYMBOL:					break;				default:					if (msg_ok)						scanerror(T_SEMICOLON, 						    "Filename expected");					return FALSE;			}			strcpy(name, tokenstring());		} else {			*once = FALSE;		}	}	/* look at the next token */	switch (gettoken()) {		case T_SEMICOLON:		case T_NEWLINE:		case T_EOF:			break;		default:			if (msg_ok)				scanerror(T_SEMICOLON, 				    "Missing semicolon after filename");			return FALSE;	}	return TRUE;}/* * Read the show command and display useful information. */static voidgetshowcommand(){	char name[SYMBOLSIZE+1];	if ((gettoken() != T_SHOW) || (gettoken() != T_SYMBOL)) {		scanerror(T_SEMICOLON, "Bad syntax for SHOW command");		return;	}	strcpy(name, tokenstring());	switch (gettoken()) {		case T_NEWLINE:		case T_SEMICOLON:			break;		default:			scanerror(T_SEMICOLON, "Bad syntax for SHOW command");	}	switch ((int) stringindex("builtins\0builtin\0globals\0global\0functions\0function\0objfuncs\0objfunc\0memory\0", name)) {		case 1:		case 2:			showbuiltins();			break;		case 3:		case 4:			showglobals();			break;		case 5:		case 6:			showfunctions();			break;		case 7:		case 8:			showobjfuncs();			break;		case 9:			mem_stats("");			break;		default:			scanerror(T_NULL, "Unknown SHOW parameter \"%s\"", name);	}}/* * Read in a set of matrix index arguments, surrounded with square brackets. * This also handles double square brackets for 'fast indexing'. */static voidgetmatargs(){	int dim;	if (gettoken() != T_LEFTBRACKET) {		scanerror(T_NULL, "Matrix indexing expected");		return;	}	/*	 * Parse all levels of the array reference	 * Look for the 'fast index' first.	 */	if (gettoken() == T_LEFTBRACKET) {		(void) getassignment();		if ((gettoken() != T_RIGHTBRACKET) ||			(gettoken() != T_RIGHTBRACKET)) {				scanerror(T_NULL, "Bad fast index usage");				return;		}		addop(OP_FIADDR);		return;	}	rescantoken();	/*	 * Normal indexing with the indexes separated by commas.	 * Initialize the flag in the opcode to assume that the array	 * element will only be referenced for reading.  If the parser	 * finds that the element will be referenced for writing, then	 * it will call writeindexop to change the flag in the opcode.	 */	dim = 1;	for (;;) {		(void) getassignment();		switch (gettoken()) {			case T_RIGHTBRACKET:				if (gettoken() != T_LEFTBRACKET) {					rescantoken();					addoptwo(OP_INDEXADDR, (long) dim,						(long) FALSE);					return;				}				/* proceed into comma case */				/*FALLTHRU*/			case T_COMMA:				if (++dim > MAXDIM)					scanerror(T_NULL, "Too many dimensions for array reference");				break;			default:				rescantoken();				scanerror(T_NULL, "Missing right bracket in array reference");				return;		}	}}/* * Get an element of an object reference. * The leading period which introduces the element has already been read. */static voidgetelement(){	long index;	char name[SYMBOLSIZE+1];	if (!getid(name))		return;	index = findelement(name);	if (index < 0) {		scanerror(T_NULL, "Element \"%s\" is undefined", name);		return;	}	addopone(OP_ELEMADDR, index);}/* * Read in a single symbol name and copy its value into the given buffer. * Returns TRUE if a valid symbol id was found. */static BOOLgetid(buf)	char buf[SYMBOLSIZE+1];{	int type;	type = gettoken();	if (iskeyword(type)) {		scanerror(T_NULL, "Reserved keyword used as symbol name");		type = T_SYMBOL;	}	if (type != T_SYMBOL) {		rescantoken();		scanerror(T_NULL, "Symbol name expected");		*buf = '\0';		return FALSE;	}	strncpy(buf, tokenstring(), SYMBOLSIZE);	buf[SYMBOLSIZE] = '\0';	return TRUE;}/* * Define a symbol name to be of the specified symbol type.  This also checks * to see if the symbol was already defined in an incompatible manner. */static voiddefinesymbol(name, symtype)	int symtype;	char *name;{	switch (symboltype(name)) {		case SYM_UNDEFINED:		case SYM_GLOBAL:		case SYM_STATIC:			if (symtype == SYM_LOCAL)				(void) addlocal(name);			else				(void) addglobal(name, (symtype == SYM_STATIC));			break;		case SYM_PARAM:		case SYM_LOCAL:			scanerror(T_COMMA, "Variable \"%s\" is already defined", name);			return;	}}/* * Check a symbol name to see if it is known and generate code to reference it. * The symbol can be either a parameter name, a local name, or a global name. * If autodef is true, we automatically define the name as a global symbol * if it is not yet known. */static voidusesymbol(name, autodef)	char *name;		/* symbol name to be checked */	BOOL autodef;{	switch (symboltype(name)) {		case SYM_LOCAL:			addopone(OP_LOCALADDR, (long) findlocal(name));			return;		case SYM_PARAM:			addopone(OP_PARAMADDR, (long) findparam(name));			return;		case SYM_GLOBAL:		case SYM_STATIC:			addopptr(OP_GLOBALADDR, (char *) findglobal(name));			return;	}	/*	 * The symbol is not yet defined.	 * If we are at the top level and we are allowed to, then define it.	 */	if ((curfunc->f_name[0] != '*') || !autodef) {		scanerror(T_NULL, "\"%s\" is undefined", name);		return;	}	(void) addglobal(name, FALSE);	addopptr(OP_GLOBALADDR, (char *) findglobal(name));}/* * Get arguments for a function call. * The name and beginning parenthesis has already been seen. * callargs = [ [ '&' ] assignment  [',' [ '&' ] assignment] ] ')'. */static voidgetcallargs(name)	char *name;		/* name of function */{	long index;		/* function index */	long op;		/* opcode to add */	int argcount;		/* number of arguments */	int type;	BOOL addrflag;	op = OP_CALL;	index = getbuiltinfunc(name);	if (index < 0) {		op = OP_USERCALL;		index = adduserfunc(name);	}	if (gettoken() == T_RIGHTPAREN) {		if (op == OP_CALL)			builtincheck(index, 0);		addopfunction(op, index, 0);		return;	}	rescantoken();	argcount = 0;	for (;;) {		argcount++;		addrflag = (gettoken() == T_AND);		if (!addrflag)			rescantoken();		type = getassignment();		if (addrflag) {			if (isrvalue(type))				scanerror(T_NULL, "Taking address of non-variable");			writeindexop();		}		if (!addrflag && (op != OP_CALL))			addop(OP_GETVALUE);		switch (gettoken()) {			case T_RIGHTPAREN:				if (op == OP_CALL)					builtincheck(index, argcount);				addopfunction(op, index, argcount);				return;			case T_COMMA:				break;			default:				scanerror(T_SEMICOLON, "Missing right parenthesis in function call");				return;		}	}}/* END CODE */

⌨️ 快捷键说明

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