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

📄 ejsparser.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	@file 	ejsParser.c *	@brief 	EJS Parser and Execution  *//********************************* Copyright **********************************//* *	@copy	default.g *	 *	Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. *	Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. *	 *	This software is distributed under commercial and open source licenses. *	You may use the GPL open source license described below or you may acquire  *	a commercial license from Mbedthis Software. You agree to be fully bound  *	by the terms of either license. Consult the LICENSE.TXT distributed with  *	this software for full details. *	 *	This software is open source; you can redistribute it and/or modify it  *	under the terms of the GNU General Public License as published by the  *	Free Software Foundation; either version 2 of the License, or (at your  *	option) any later version. See the GNU General Public License for more  *	details at: http://www.mbedthis.com/downloads/gplLicense.html *	 *	This program is distributed WITHOUT ANY WARRANTY; without even the  *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  *	 *	This GPL license does NOT permit incorporating this software into  *	proprietary programs. If you are unable to comply with the GPL, you must *	acquire a commercial license to use this software. Commercial licenses  *	for this software and support services are available from Mbedthis  *	Software at http://www.mbedthis.com  *	 *	@end *//********************************** Includes **********************************/#include	"ejs.h"#if BLD_FEATURE_EJS/****************************** Forward Declarations **************************/static int 		createClass(Ejs *ep, EjsVar *parentClass, 					const char *className, EjsVar *baseClass);static int 		createProperty(Ejs *ep, EjsVar **obj, const char *id, 					int state);static int		evalCond(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs);static int		evalExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs);#if BLD_FEATURE_FLOATING_POINTstatic int 		evalFloatExpr(Ejs *ep, double l, int rel, double r);#endif static int 		evalBoolExpr(Ejs *ep, int l, int rel, int r);static int 		evalNumericExpr(Ejs *ep, EjsNum l, int rel, EjsNum r);static int 		evalObjExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs) ;static int 		evalStringExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs);static int		evalMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, int flags);static EjsProperty *findProperty(Ejs *ep, EjsVar *op, const char *property, 					int flags);static EjsVar 	*pickSpace(Ejs *ep, int state, const char *property, int flags);static void		freeProc(Ejs *ep, EjsProc *proc);static int		parseArgs(Ejs *ep, int state, int flags);static int 		parseArrayLiteral(Ejs *ep, int state, int flags, char *id);static int		parseAssignment(Ejs *ep, int state, int flags, char *id);static int 		parseClass(Ejs *ep, int state, int flags);static int 		parseForInner(Ejs *ep, int state, int flags, 					EjsInput *condScript, EjsInput *incrScript, 					EjsInput *bodyScript, EjsInput *endScript);static int		parseCond(Ejs *ep, int state, int flags);static int		parseDeclaration(Ejs *ep, int state, int flags);static int		parseExpr(Ejs *ep, int state, int flags);static int 		parseFor(Ejs *ep, int state, int flags);static int 		parseRegFor(Ejs *ep, int state, int flags);static int 		parseForIn(Ejs *ep, int state, int flags, int each);static int 		parseId(Ejs *ep, int state, int flags, char **id, int *done);static int 		parseInc(Ejs *ep, int state, int flags);static int 		parseIf(Ejs *ep, int state, int flags, int *done);static int		parseFunction(Ejs *ep, int state, int flags);static int		parseMethod(Ejs *ep, int state, int flags, char *id);static int 		parseObjectLiteral(Ejs *ep, int state, int flags, char *id);static int		parseStmt(Ejs *ep, int state, int flags);static int 		parseThrow(Ejs *ep, int state, int flags);static int 		parseTry(Ejs *ep, int state, int flags);static void 	removeNewlines(Ejs *ep, int state);static EjsProperty *searchSpacesForProperty(Ejs *ep, int state, EjsVar *obj, 					char *property, int flags);static int 		assignPropertyValue(Ejs *ep, char *id, int state, EjsVar *value,					int flags);static int 		updateProperty(Ejs *ep, EjsVar *obj, const char *id, int state,					EjsVar *value);static void 	updateResult(Ejs *ep, int state, int flags, EjsVar *vp);static int 		getNextNonSpaceToken(Ejs *ep, int state);static int 		callConstructor(Ejs *ep, EjsVar *thisObj, EjsVar *baseClass, 					MprArray *args);static int 		callCMethod(Ejs *ep, EjsVar *obj, EjsProc *proc,					EjsVar *prototype);static int 		callStringCMethod(Ejs *ep, EjsVar *obj, EjsProc *proc,					EjsVar *prototype);static int 		callMethod(Ejs *ep, EjsVar *obj, EjsProc *proc,					EjsVar *prototype);static int 		runMethod(Ejs *ep, EjsVar *thisObj, EjsVar *method, 					const char *methodName, MprArray *args);static EjsInput *getInputStruct(Ejs *ep);static void 	freeInputStruct(Ejs *ep, EjsInput *input);static void 	*pushFrame(Ejs *ep, int size);static void 	*popFrame(Ejs *ep, int size);/************************************* Code ***********************************//* *	Recursive descent parser for EJS */int ejsParse(Ejs *ep, int state, int flags){	mprAssert(ep);#if MOB	if (mprStackCheck(ep)) {		char	*stack;		stack = ejsFormatStack(ep);		mprLog(ep, 0, "\nStack grew : MAX %d\n", mprStackSize(ep));		mprLog(ep, 0, "Stack\n %s\n", stack);		mprFree(stack);	}#endif	if (ep->flags & EJS_FLAGS_EXIT) {		return EJS_STATE_RET;	}	ep->inputMarker = ep->input->scriptServp;	switch (state) {	/*	 *	Any statement, method arguments or conditional expressions	 */	case EJS_STATE_STMT:		state = parseStmt(ep, state, flags);		if (state != EJS_STATE_STMT_BLOCK_DONE && state != EJS_STATE_STMT_DONE){			goto err;		}		break;	case EJS_STATE_DEC:		state = parseStmt(ep, state, flags);		if (state != EJS_STATE_DEC_DONE) {			goto err;		}		break;	case EJS_STATE_EXPR:		state = parseStmt(ep, state, flags);		if (state != EJS_STATE_EXPR_DONE) {			goto err;		}		break;	/*	 *	Variable declaration list	 */	case EJS_STATE_DEC_LIST:		state = parseDeclaration(ep, state, flags);		if (state != EJS_STATE_DEC_LIST_DONE) {			goto err;		}		break;	/*	 *	Method argument string	 */	case EJS_STATE_ARG_LIST:		state = parseArgs(ep, state, flags);		if (state != EJS_STATE_ARG_LIST_DONE) {			goto err;		}		break;	/*	 *	Logical condition list (relational operations separated by &&, ||)	 */	case EJS_STATE_COND:		state = parseCond(ep, state, flags);		if (state != EJS_STATE_COND_DONE) {			goto err;		}		break;	/*	 *	Expression list	 */	case EJS_STATE_RELEXP:		state = parseExpr(ep, state, flags);		if (state != EJS_STATE_RELEXP_DONE) {			goto err;		}		break;	}	/* 	 *	Recursion protection	 */	if (ep->input->scriptServp == ep->inputMarker) {		if (ep->recurseCount++ > 20) {			ejsSyntaxError(ep, "Input syntax error");			state = EJS_STATE_ERR;		}	} else {		ep->recurseCount = 0;	}	if (state == EJS_STATE_RET || state == EJS_STATE_EOF) {		return state;	}done:	return state;err:	if (state == EJS_STATE_RET || state == EJS_STATE_EOF) {		goto done;	}	if (state != EJS_STATE_ERR) {		ejsSyntaxError(ep, 0);	}	state = EJS_STATE_ERR;	goto done;}/******************************************************************************//* *	Local vars  */typedef struct ParseStmt {	EjsProc		*saveProc;	EjsProperty	*pp;	EjsVar		*saveObj, *exception;	char		*str, *id;	int			done, tid, rs, saveObjPerm, expectEndOfStmt;} ParseStmt;/* *	Parse expression (leftHandSide operator rightHandSide) */static int parseStmt(Ejs *ep, int state, int flags){	ParseStmt		*sp;	mprAssert(ep);	if ((sp = pushFrame(ep, sizeof(ParseStmt))) == 0) {		return EJS_STATE_ERR;	}	sp->id = 0;	sp->expectEndOfStmt = 0;	sp->saveProc = NULL;	ep->currentObj = 0;	ep->currentProperty = 0;	for (sp->done = 0; !sp->done && state != EJS_STATE_ERR; ) {		sp->tid = ejsLexGetToken(ep, state);#if (WIN || BREW_SIMULATOR) && BLD_DEBUG && DISABLED		/* MOB -- make cross platform */		_CrtCheckMemory();#endif		switch (sp->tid) {		default:			ejsLexPutbackToken(ep, sp->tid, ep->token);			goto done;		case EJS_TOK_EXPR:			if (state == EJS_STATE_EXPR) {				ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token);			}			goto done;		case EJS_TOK_LOGICAL:			ejsLexPutbackToken(ep, sp->tid, ep->token);			goto done;		case EJS_TOK_ERR:			if (state != EJS_STATE_ERR && !ep->gotException) {				ejsSyntaxError(ep, 0);			}			state = EJS_STATE_ERR;			goto done;		case EJS_TOK_EOF:			state = EJS_STATE_EOF;			goto done;		case EJS_TOK_NEWLINE:			break;		case EJS_TOK_SEMI:			/*			 *	This case is when we discover no statement and just a lone ';'			 */			if (state != EJS_STATE_STMT) {				ejsLexPutbackToken(ep, sp->tid, ep->token);			}			goto done;		case EJS_TOK_LBRACKET:			if (flags & EJS_FLAGS_EXE) {				ep->currentObj = &ep->currentProperty->var;				if (ep->currentObj != 0 && ep->currentObj->type != 						EJS_TYPE_OBJECT) {					ejsError(ep, EJS_REFERENCE_ERROR,						"Property reference to a non-object type \"%s\"\n", 						sp->id);					goto err;				}			}			sp->saveObj = ep->currentObj;			sp->saveObjPerm = ejsMakeObjPermanent(sp->saveObj, 1);			sp->rs = ejsParse(ep, EJS_STATE_RELEXP, flags);			ejsMakeObjPermanent(sp->saveObj, sp->saveObjPerm);			ep->currentObj = sp->saveObj;			if (sp->rs < 0) {				state = sp->rs;				goto done;			}			mprFree(sp->id);			/* MOB rc */			sp->str = ejsVarToString(ep, ep->result);			sp->id = mprStrdup(ep, sp->str);			if (sp->id[0] == '\0') {				if (flags & EJS_FLAGS_EXE) {					ejsError(ep, EJS_RANGE_ERROR,						"[] expression evaluates to the empty string\n");					goto err;				}			} else {				sp->pp = searchSpacesForProperty(ep, state, ep->currentObj, 					sp->id, flags);				ep->currentProperty = sp->pp;				updateResult(ep, state, flags, ejsGetVarPtr(sp->pp));			}			if ((sp->tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) {				ejsSyntaxError(ep, "Missing ']'");				goto err;			}			break;		case EJS_TOK_PERIOD:			if (flags & EJS_FLAGS_EXE) {				if (ep->currentProperty == 0) {					ejsError(ep, EJS_REFERENCE_ERROR,						"Undefined object \"%s\"", sp->id);					goto err;				}			}			ep->currentObj = &ep->currentProperty->var;			if (flags & EJS_FLAGS_EXE) {				if (ep->currentObj != 0 && ep->currentObj->type != 						EJS_TYPE_OBJECT) {					ejsError(ep, EJS_REFERENCE_ERROR,						"Property reference to a non-object type \"%s\"\n",						sp->id);					goto err;				}			}			if ((sp->tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) {				ejsError(ep, EJS_REFERENCE_ERROR, "Bad property after '.': %s", 					ep->token);				goto err;			}			/* Fall through */		case EJS_TOK_ID:			state = parseId(ep, state, flags, &sp->id, &sp->done);			if (sp->done && state == EJS_STATE_STMT) {				sp->expectEndOfStmt = 1;			}			break;		case EJS_TOK_ASSIGNMENT:			sp->tid = ejsLexGetToken(ep, state);			if (sp->tid == EJS_TOK_LBRACE) {				/* 				 *	var = { name: value, name: value, ... } 				 */				if (parseObjectLiteral(ep, state, flags, sp->id) < 0) {					ejsSyntaxError(ep, "Bad object literal");					goto err;				}			} else if (sp->tid == EJS_TOK_LBRACKET) {				/* 				 *	var = [ array elements ] 				 */				if (parseArrayLiteral(ep, state, flags, sp->id) < 0) {					ejsSyntaxError(ep, "Bad array literal");					goto err;				}			} else if (sp->tid == EJS_TOK_EXPR && 					(int) *ep->token == EJS_EXPR_LESS) {				/* 				 *	var = <xmlTag> .../</xmlTag>				 */				ejsSyntaxError(ep, "XML literals are not yet supported");				goto err;			} else {				/* 				 *	var = expression				 */				ejsLexPutbackToken(ep, sp->tid, ep->token);				state = parseAssignment(ep, state, flags, sp->id);				if (state == EJS_STATE_ERR) {					if (ep->flags & EJS_FLAGS_EXIT) {						state = EJS_STATE_RET;						goto done;					}					if (!ep->gotException) {						ejsSyntaxError(ep, 0);					}					goto err;				}			}			if (flags & EJS_FLAGS_EXE) {				if (assignPropertyValue(ep, sp->id, state, ep->result, 							flags) < 0) {					if (ep->gotException == 0) {						ejsError(ep, EJS_EVAL_ERROR, "Can't set property %s", 							sp->id);					}					goto err;				}			}			if (state == EJS_STATE_STMT) {				sp->expectEndOfStmt = 1;				goto done;			}			break;		case EJS_TOK_INC_DEC:			state = parseInc(ep, state, flags);			if (state == EJS_STATE_STMT) {				sp->expectEndOfStmt = 1;			}			break;		case EJS_TOK_NEW:			/* MOB -- could we remove rs and just use state */			sp->rs = ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW);			if (sp->rs < 0) {				state = sp->rs;				goto done;			}			break;		case EJS_TOK_DELETE:			sp->rs = ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_DELETE);			if (sp->rs < 0) {				state = sp->rs;				goto done;			}			if (flags & EJS_FLAGS_EXE) {				/* Single place where properties are deleted */				if (ep->currentObj == 0 || ep->currentProperty == 0) {					ejsError(ep, EJS_EVAL_ERROR, 						"Can't find property to delete"); 					goto err;				}				if (ep->currentObj->isArray) {					ejsSetArrayLength(ep, ep->currentObj, 0, 						ep->currentProperty->name, 0);				}				ejsDeleteProperty(ep, ep->currentObj, 					ep->currentProperty->name);				ep->currentProperty = 0;			}			goto done;		case EJS_TOK_FUNCTION:			/*			 *	Parse a function declaration 			 */			state = parseFunction(ep, state, flags);			goto done;		case EJS_TOK_THROW:			state = parseThrow(ep, state, flags);			goto done;		case EJS_TOK_TRY:			state = parseTry(ep, state, flags);			goto done;		case EJS_TOK_CLASS:		case EJS_TOK_MODULE:			state = parseClass(ep, state, flags);			goto done;		case EJS_TOK_LITERAL:			/*			 *	Set the result to the string literal 			 */			if (flags & EJS_FLAGS_EXE) {				ejsWriteVarAsString(ep, ep->result, ep->token);				ejsSetVarName(ep, ep->result, "");			}			if (state == EJS_STATE_STMT) {				sp->expectEndOfStmt = 1;			}			goto done;		case EJS_TOK_NUMBER:			/*			 *	Set the result to the parsed number			 */			if (flags & EJS_FLAGS_EXE) {				ejsWriteVar(ep, ep->result, &ep->tokenNumber, 0);			}			if (state == EJS_STATE_STMT) {				sp->expectEndOfStmt = 1;			}			goto done;		case EJS_TOK_METHOD_NAME:			/*			 *	parse a method() invocation			 */			mprAssert(ep->currentObj);			state = parseMethod(ep, state, flags, sp->id);			if (state == EJS_STATE_STMT) {				sp->expectEndOfStmt = 1;			}			if (ep->flags & EJS_FLAGS_EXIT) {				state = EJS_STATE_RET;			}			goto done;		case EJS_TOK_IF:			state = parseIf(ep, state, flags, &sp->done);			if (state < 0) {				goto done;			}			break;		case EJS_TOK_FOR:			state = parseFor(ep, state, flags);			goto done;		case EJS_TOK_VAR:			if ((sp->rs = ejsParse(ep, EJS_STATE_DEC_LIST, flags)) < 0) {				state = sp->rs;				goto done;			}			goto done;

⌨️ 快捷键说明

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