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

📄 ejparse.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
				freeFunc(&func);				goto error;			}			if (parse(ep, STATE_ARG_LIST, flags) != STATE_ARG_LIST_DONE) {				freeFunc(&func);				ep->func = saveFunc;				goto error;			}/* *			Evaluate the function if required */			if (flags & FLAGS_EXE && evalFunction(ep) < 0) {				freeFunc(&func);				ep->func = saveFunc;				goto error;			}			freeFunc(&func);			ep->func = saveFunc;			if (ejLexGetToken(ep, state) != TOK_RPAREN) {				goto error;			}			if (state == STATE_STMT) {				expectSemi++;			}			done++;			break;		case TOK_IF:			if (state != STATE_STMT) {				goto error;			}			if (ejLexGetToken(ep, state) != TOK_LPAREN) {				goto error;			}/* *			Evaluate the entire condition list "(condition)" */			if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {				goto error;			}			if (ejLexGetToken(ep, state) != TOK_RPAREN) {				goto error;			}/* *			This is the "then" case. We need to always parse both cases and *			execute only the relevant case. */			if (*ep->result == '1') {				thenFlags = flags;				elseFlags = flags & ~FLAGS_EXE;			} else {				thenFlags = flags & ~FLAGS_EXE;				elseFlags = flags;			}/* *			Process the "then" case.  Allow for RETURN statement */			switch (parse(ep, STATE_STMT, thenFlags)) {			case STATE_RET:				return STATE_RET;			case STATE_STMT_DONE:				break;			default:				goto error;			}/* *			check to see if there is an "else" case */			ejRemoveNewlines(ep, state);			tid = ejLexGetToken(ep, state);			if (tid != TOK_ELSE) {				ejLexPutbackToken(ep, tid, ep->token);				done++;				break;			}/* *			Process the "else" case.  Allow for return. */			switch (parse(ep, STATE_STMT, elseFlags)) {			case STATE_RET:				return STATE_RET;			case STATE_STMT_DONE:				break;			default:				goto error;			}			done++;			break;		case TOK_FOR:/* *			Format for the expression is: * *				for (initial; condition; incr) { *					body; *				} */			if (state != STATE_STMT) {				goto error;			}			if (ejLexGetToken(ep, state) != TOK_LPAREN) {				goto error;			}/* *			Evaluate the for loop initialization statement */			if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) {				goto error;			}			if (ejLexGetToken(ep, state) != TOK_SEMI) {				goto error;			}/* *			The first time through, we save the current input context just *			to each step: prior to the conditional, the loop increment and the *			loop body. */			ejLexSaveInputState(ep, &condScript);			if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {				goto error;			}			cond = (*ep->result != '0');			if (ejLexGetToken(ep, state) != TOK_SEMI) {				goto error;			}/* *			Don't execute the loop increment statement or the body first time */			forFlags = flags & ~FLAGS_EXE;			ejLexSaveInputState(ep, &incrScript);			if (parse(ep, STATE_EXPR, forFlags) != STATE_EXPR_DONE) {				goto error;			}			if (ejLexGetToken(ep, state) != TOK_RPAREN) {				goto error;			}/* *			Parse the body and remember the end of the body script */			ejLexSaveInputState(ep, &bodyScript);			if (parse(ep, STATE_STMT, forFlags) != STATE_STMT_DONE) {				goto error;			}			ejLexSaveInputState(ep, &endScript);/* *			Now actually do the for loop. Note loop has been rotated */			while (cond && (flags & FLAGS_EXE) ) {/* *				Evaluate the body */				ejLexRestoreInputState(ep, &bodyScript);				switch (parse(ep, STATE_STMT, flags)) {				case STATE_RET:					return STATE_RET;				case STATE_STMT_DONE:					break;				default:					goto error;				}/* *				Evaluate the increment script */				ejLexRestoreInputState(ep, &incrScript);				if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) {					goto error;				}/* *				Evaluate the condition */				ejLexRestoreInputState(ep, &condScript);				if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {					goto error;				}				cond = (*ep->result != '0');			}			ejLexRestoreInputState(ep, &endScript);			done++;			break;		case TOK_VAR:			if (parse(ep, STATE_DEC_LIST, flags) != STATE_DEC_LIST_DONE) {				goto error;			}			done++;			break;		case TOK_COMMA:			ejLexPutbackToken(ep, TOK_EXPR, ep->token);			done++;			break;		case TOK_LPAREN:			if (state == STATE_EXPR) {				if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {					goto error;				}				if (ejLexGetToken(ep, state) != TOK_RPAREN) {					goto error;				}				return STATE_EXPR_DONE;			}			done++;			break;		case TOK_RPAREN:			ejLexPutbackToken(ep, tid, ep->token);			return STATE_EXPR_DONE;		case TOK_LBRACE:/* *			This handles any code in braces except "if () {} else {}" */			if (state != STATE_STMT) {				goto error;			}/* *			Parse will return STATE_STMT_BLOCK_DONE when the RBRACE is seen */			do {				state = parse(ep, STATE_STMT, flags);			} while (state == STATE_STMT_DONE);/* *			Allow return statement. */			if (state == STATE_RET) {				return state;			}			if (ejLexGetToken(ep, state) != TOK_RBRACE) {				goto error;			}			return STATE_STMT_DONE;		case TOK_RBRACE:			if (state == STATE_STMT) {				ejLexPutbackToken(ep, tid, ep->token);				return STATE_STMT_BLOCK_DONE;			}			goto error;		case TOK_RETURN:			if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {				goto error;			}			if (flags & FLAGS_EXE) {				while ( ejLexGetToken(ep, state) != TOK_EOF );				done++;				return STATE_RET;			}			break;		}	}	if (expectSemi) {		tid = ejLexGetToken(ep, state);		if (tid != TOK_SEMI && tid != TOK_NEWLINE) {			goto error;		}/* *		Skip newline after semi-colon */		ejRemoveNewlines(ep, state);	}/* *	Free resources and return the correct status */doneParse:	if (tid == TOK_FOR) {		ejLexFreeInputState(ep, &condScript);		ejLexFreeInputState(ep, &incrScript);		ejLexFreeInputState(ep, &endScript);		ejLexFreeInputState(ep, &bodyScript);	}	if (state == STATE_STMT) {		return STATE_STMT_DONE;	} else if (state == STATE_DEC) {		return STATE_DEC_DONE;	} else if (state == STATE_EXPR) {		return STATE_EXPR_DONE;	} else if (state == STATE_EOF) {		return state;	} else {		return STATE_ERR;	}/* *	Common error exit */error:	state = STATE_ERR;	goto doneParse;}/******************************************************************************//* *	Parse variable declaration list */static int parseDeclaration(ej_t *ep, int state, int flags){	int		tid;	a_assert(ep);/* *	Declarations can be of the following forms: *			var x; *			var x, y, z; *			var x = 1 + 2 / 3, y = 2 + 4; * *	We set the variable to NULL if there is no associated assignment. */	do {		if ((tid = ejLexGetToken(ep, state)) != TOK_ID) {			return STATE_ERR;		}		ejLexPutbackToken(ep, tid, ep->token);/* *		Parse the entire assignment or simple identifier declaration */		if (parse(ep, STATE_DEC, flags) != STATE_DEC_DONE) {			return STATE_ERR;		}/* *		Peek at the next token, continue if comma seen */		tid = ejLexGetToken(ep, state);		if (tid == TOK_SEMI) {			return STATE_DEC_LIST_DONE;		} else if (tid != TOK_COMMA) {			return STATE_ERR;		}	} while (tid == TOK_COMMA);	if (tid != TOK_SEMI) {		return STATE_ERR;	}	return STATE_DEC_LIST_DONE;}/******************************************************************************//* *	Parse function arguments */static int parseArgs(ej_t *ep, int state, int flags){	int		tid, aid;	a_assert(ep);	do {		state = parse(ep, STATE_RELEXP, flags);		if (state == STATE_EOF || state == STATE_ERR) {			return state;		}		if (state == STATE_RELEXP_DONE) {			aid = hAlloc((void***) &ep->func->args);			ep->func->args[aid] = bstrdup(B_L, ep->result);			ep->func->nArgs++;		}/* *		Peek at the next token, continue if more args (ie. comma seen) */		tid = ejLexGetToken(ep, state);		if (tid != TOK_COMMA) {			ejLexPutbackToken(ep, tid, ep->token);		}	} while (tid == TOK_COMMA);	if (tid != TOK_RPAREN && state != STATE_RELEXP_DONE) {		return STATE_ERR;	}	return STATE_ARG_LIST_DONE;}/******************************************************************************//* *	Parse conditional expression (relational ops separated by ||, &&) */static int parseCond(ej_t *ep, int state, int flags){	char_t	*lhs, *rhs;	int		tid, operator;	a_assert(ep);	setString(B_L, &ep->result, T(""));	rhs = lhs = NULL;	operator = 0;	do {/* *	Recurse to handle one side of a conditional. Accumulate the *	left hand side and the final result in ep->result. */		state = parse(ep, STATE_RELEXP, flags);		if (state != STATE_RELEXP_DONE) {			state = STATE_ERR;			break;		}		if (operator > 0) {			setString(B_L, &rhs, ep->result);			if (evalCond(ep, lhs, operator, rhs) < 0) {				state = STATE_ERR;				break;			}		}		setString(B_L, &lhs, ep->result);		tid = ejLexGetToken(ep, state);		if (tid == TOK_LOGICAL) {			operator = (int) *ep->token;		} else if (tid == TOK_RPAREN || tid == TOK_SEMI) {			ejLexPutbackToken(ep, tid, ep->token);			state = STATE_COND_DONE;			break;		} else {			ejLexPutbackToken(ep, tid, ep->token);		}	} while (state == STATE_RELEXP_DONE);	if (lhs) {		bfree(B_L, lhs);	}	if (rhs) {		bfree(B_L, rhs);	}	return state;}/******************************************************************************//* *	Parse expression (leftHandSide operator rightHandSide) */static int parseExpr(ej_t *ep, int state, int flags){	char_t	*lhs, *rhs;	int		rel, tid;	a_assert(ep);	setString(B_L, &ep->result, T(""));	rhs = lhs = NULL;	rel = 0;	tid = 0;	do {/* *	This loop will handle an entire expression list. We call parse *	to evalutate each term which returns the result in ep->result. */		if (tid == TOK_LOGICAL) {			if ((state = parse(ep, STATE_RELEXP, flags)) != STATE_RELEXP_DONE) {				state = STATE_ERR;				break;			}		} else {			if ((state = parse(ep, STATE_EXPR, flags)) != STATE_EXPR_DONE) {				state = STATE_ERR;				break;			}		}		if (rel > 0) {			setString(B_L, &rhs, ep->result);			if (tid == TOK_LOGICAL) {				if (evalCond(ep, lhs, rel, rhs) < 0) {					state = STATE_ERR;					break;				}			} else {				if (evalExpr(ep, lhs, rel, rhs) < 0) {					state = STATE_ERR;					break;				}			}		}		setString(B_L, &lhs, ep->result);		if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR ||			 tid == TOK_INC_DEC || tid == TOK_LOGICAL) {			rel = (int) *ep->token;		} else {			ejLexPutbackToken(ep, tid, ep->token);			state = STATE_RELEXP_DONE;		}	} while (state == STATE_EXPR_DONE);	if (rhs) {		bfree(B_L, rhs);	}	if (lhs) {		bfree(B_L, lhs);	}	return state;}/******************************************************************************//* *	Evaluate a condition. Implements &&, ||, ! */static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs){	char_t	buf[16];	int		l, r, lval;	a_assert(lhs);	a_assert(rhs);	a_assert(rel > 0);	lval = 0;	if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) {		l = gatoi(lhs);		r = gatoi(rhs);		switch (rel) {		case COND_AND:			lval = l && r;			break;		case COND_OR:			lval = l || r;			break;		default:			ejError(ep, T("Bad operator %d"), rel);			return -1;		}	} else {		if (!gisdigit((int)*lhs)) {			ejError(ep, T("Conditional must be numeric"), lhs);		} else {			ejError(ep, T("Conditional must be numeric"), rhs);		}	}	stritoa(lval, buf, sizeof(buf));	setString(B_L, &ep->result, buf);	return 0;}/******************************************************************************//* *	Evaluate an operation */static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs){	char_t	*cp, buf[16];	int		numeric, l, r, lval;	a_assert(lhs);	a_assert(rhs);	a_assert(rel > 0);/* *	All of the characters in the lhs and rhs must be numeric */	numeric = 1;	for (cp = lhs; *cp; cp++) {		if (!gisdigit((int)*cp)) {			numeric = 0;			break;		}	}	if (numeric) {		for (cp = rhs; *cp; cp++) {			if (!gisdigit((int)*cp)) {				numeric = 0;				break;			}

⌨️ 快捷键说明

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