ejslex.c

来自「samba最新软件」· C语言 代码 · 共 924 行 · 第 1/2 页

C
924
字号
/* *	@file 	ejsLex.c *	@brief 	EJS Lexical Analyser *	@overview EJS lexical analyser. This implementes a lexical analyser  *		for a subset of the JavaScript language. *//********************************* Copyright **********************************//* *	@copy	default.g *	 *	Copyright (c) Mbedthis Software LLC, 2003-2005. 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	"ejsInternal.h"#if BLD_FEATURE_EJS/****************************** Forward Declarations **************************/static int 		getLexicalToken(Ejs *ep, int state);static int 		tokenAddChar(Ejs *ep, int c);static int 		inputGetc(Ejs *ep);static void		inputPutback(Ejs *ep, int c);static int		charConvert(Ejs *ep, int base, int maxDig);/************************************* Code ***********************************//* *	Open a new input script */int ejsLexOpenScript(Ejs *ep, char *script){	EjsInput	*ip;	mprAssert(ep);	mprAssert(script);	if ((ip = mprMalloc(sizeof(EjsInput))) == NULL) {		return -1;	}	memset(ip, 0, sizeof(*ip));	ip->next = ep->input;	ep->input = ip;	ip->procName = ep->proc?ep->proc->procName:NULL;/* *	Create the parse token buffer and script buffer */	ip->tokbuf = mprMalloc(EJS_PARSE_INCR);	ip->tokSize = EJS_PARSE_INCR; 	ip->tokServp = ip->tokbuf;	ip->tokEndp = ip->tokbuf;	ip->script = mprStrdup(script);	ip->scriptSize = strlen(script);	ip->scriptServp = ip->script;	ip->lineNumber = 1;	ip->lineLength = 0;	ip->lineColumn = 0;	ip->line = NULL;	ip->putBackIndex = -1;	return 0;}/******************************************************************************//* *	Close the input script */void ejsLexCloseScript(Ejs *ep){	EjsInput	*ip;	int			i;	mprAssert(ep);	ip = ep->input;	mprAssert(ip);	ep->input = ip->next;	for (i = 0; i < EJS_TOKEN_STACK; i++) {		mprFree(ip->putBack[i].token);		ip->putBack[i].token = 0;	}	mprFree(ip->line);	mprFree(ip->tokbuf);	mprFree(ip->script);	mprFree(ip);}/******************************************************************************//* *	Initialize an input state structure */int ejsInitInputState(EjsInput *ip){	mprAssert(ip);	memset(ip, 0, sizeof(*ip));	ip->putBackIndex = -1;	return 0;}/******************************************************************************//* *	Save the input state */void ejsLexSaveInputState(Ejs *ep, EjsInput *state){	EjsInput	*ip;	int			i;	mprAssert(ep);	ip = ep->input;	mprAssert(ip);	*state = *ip;	for (i = 0; i < ip->putBackIndex; i++) {		state->putBack[i].token = mprStrdup(ip->putBack[i].token);		state->putBack[i].id = ip->putBack[i].id;	}	for (; i < EJS_TOKEN_STACK; i++) {		state->putBack[i].token = 0;	}	state->line = mprMalloc(ip->lineLength);	mprStrcpy(state->line, ip->lineLength, ip->line);	state->lineColumn = ip->lineColumn;	state->lineNumber = ip->lineNumber;	state->lineLength = ip->lineLength;}/******************************************************************************//* *	Restore the input state */void ejsLexRestoreInputState(Ejs *ep, EjsInput *state){	EjsInput	*ip;	int			i;	mprAssert(ep);	mprAssert(state);	ip = ep->input;	mprAssert(ip);	ip->tokbuf = state->tokbuf;	ip->tokServp = state->tokServp;	ip->tokEndp = state->tokEndp;	ip->tokSize = state->tokSize;	ip->script = state->script;	ip->scriptServp = state->scriptServp;	ip->scriptSize = state->scriptSize;	ip->putBackIndex = state->putBackIndex;	for (i = 0; i < ip->putBackIndex; i++) {		mprFree(ip->putBack[i].token);		ip->putBack[i].id = state->putBack[i].id;		ip->putBack[i].token = mprStrdup(state->putBack[i].token);	}	mprFree(ip->line);	ip->line = mprMalloc(state->lineLength);	mprStrcpy(ip->line, state->lineLength, state->line);	ip->lineColumn = state->lineColumn;	ip->lineNumber = state->lineNumber;	ip->lineLength = state->lineLength;}/******************************************************************************//* *	Free a saved input state */void ejsLexFreeInputState(Ejs *ep, EjsInput *state){	int			i;	mprAssert(ep);	mprAssert(state);	for (i = 0; i < EJS_TOKEN_STACK; i++) {		mprFree(state->putBack[i].token);	}	state->putBackIndex = -1;	mprFree(state->line);	state->lineLength = 0;	state->lineColumn = 0;}/******************************************************************************//* *	Get the next EJS token */int ejsLexGetToken(Ejs *ep, int state){	mprAssert(ep);	ep->tid = getLexicalToken(ep, state);	return ep->tid;}/******************************************************************************//* *	Check for reserved words "if", "else", "var", "for", "foreach", *	"delete", "function", and "return". "new", "in" and "function"  *	done below. "true", "false", "null", "undefined" are handled *	as global objects. * *	Other reserved words not supported: *		"break", "case", "catch", "continue", "default", "do",  *		"finally", "instanceof", "switch", "this", "throw", "try", *		"typeof", "while", "with" * *	ECMA extensions reserved words (not supported): *		"abstract", "boolean", "byte", "char", "class", "const", *		"debugger", "double", "enum", "export", "extends", *		"final", "float", "goto", "implements", "import", "int", *		"interface", "long", "native", "package", "private", *		"protected", "public", "short", "static", "super", *		"synchronized", "throws", "transient", "volatile" */static int checkReservedWord(Ejs *ep, int state, int c, int tid){	if (state == EJS_STATE_STMT) {		if (strcmp(ep->token, "if") == 0) {			inputPutback(ep, c);			return EJS_TOK_IF;		} else if (strcmp(ep->token, "else") == 0) {			inputPutback(ep, c);			return EJS_TOK_ELSE;		} else if (strcmp(ep->token, "var") == 0) {			inputPutback(ep, c);			return EJS_TOK_VAR;		} else if (strcmp(ep->token, "for") == 0) {			inputPutback(ep, c);			return EJS_TOK_FOR;		} else if (strcmp(ep->token, "delete") == 0) {			inputPutback(ep, c);			return EJS_TOK_DELETE;		} else if (strcmp(ep->token, "function") == 0) {			inputPutback(ep, c);			return EJS_TOK_FUNCTION;		} else if (strcmp(ep->token, "return") == 0) {			if ((c == ';') || (c == '(')) {				inputPutback(ep, c);			}			return EJS_TOK_RETURN;		}	} else if (state == EJS_STATE_EXPR) {		if (strcmp(ep->token, "new") == 0) {			inputPutback(ep, c);			return EJS_TOK_NEW;		} else if (strcmp(ep->token, "in") == 0) {			inputPutback(ep, c);			return EJS_TOK_IN;		} else if (strcmp(ep->token, "function") == 0) {			inputPutback(ep, c);			return EJS_TOK_FUNCTION;		}	}	return tid;}/******************************************************************************//* *	Get the next EJS token */static int getLexicalToken(Ejs *ep, int state){	MprType		type;	EjsInput	*ip;	int			done, tid, c, quote, style, idx;	mprAssert(ep);	ip = ep->input;	mprAssert(ip);	ep->tid = -1;	tid = -1;	type = BLD_FEATURE_NUM_TYPE_ID;	/* 	 *	Use a putback tokens first. Don't free strings as caller needs access.	 */	if (ip->putBackIndex >= 0) {		idx = ip->putBackIndex;		tid = ip->putBack[idx].id;		ep->token = (char*) ip->putBack[idx].token;		tid = checkReservedWord(ep, state, 0, tid);		ip->putBackIndex--;		return tid;	}	ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf;	*ip->tokServp = '\0';	if ((c = inputGetc(ep)) < 0) {		return EJS_TOK_EOF;	}	/* 	 *	Main lexical analyser	 */	for (done = 0; !done; ) {		switch (c) {		case -1:			return EJS_TOK_EOF;		case ' ':		case '\t':		case '\r':			do {				if ((c = inputGetc(ep)) < 0)					break;			} while (c == ' ' || c == '\t' || c == '\r');			break;		case '\n':			return EJS_TOK_NEWLINE;		case '(':			tokenAddChar(ep, c);			return EJS_TOK_LPAREN;		case ')':			tokenAddChar(ep, c);			return EJS_TOK_RPAREN;		case '[':			tokenAddChar(ep, c);			return EJS_TOK_LBRACKET;		case ']':			tokenAddChar(ep, c);			return EJS_TOK_RBRACKET;		case '.':			tokenAddChar(ep, c);			return EJS_TOK_PERIOD;		case '{':			tokenAddChar(ep, c);			return EJS_TOK_LBRACE;		case '}':			tokenAddChar(ep, c);			return EJS_TOK_RBRACE;		case '+':			if ((c = inputGetc(ep)) < 0) {				ejsError(ep, "Syntax Error");				return EJS_TOK_ERR;			}			if (c != '+' ) {				inputPutback(ep, c);				tokenAddChar(ep, EJS_EXPR_PLUS);				return EJS_TOK_EXPR;			}			tokenAddChar(ep, EJS_EXPR_INC);			return EJS_TOK_INC_DEC;		case '-':			if ((c = inputGetc(ep)) < 0) {				ejsError(ep, "Syntax Error");				return EJS_TOK_ERR;			}			if (c != '-' ) {				inputPutback(ep, c);				tokenAddChar(ep, EJS_EXPR_MINUS);				return EJS_TOK_EXPR;			}			tokenAddChar(ep, EJS_EXPR_DEC);			return EJS_TOK_INC_DEC;		case '*':			tokenAddChar(ep, EJS_EXPR_MUL);			return EJS_TOK_EXPR;		case '%':			tokenAddChar(ep, EJS_EXPR_MOD);			return EJS_TOK_EXPR;		case '/':			/*			 *	Handle the division operator and comments			 */			if ((c = inputGetc(ep)) < 0) {				ejsError(ep, "Syntax Error");				return EJS_TOK_ERR;			}			if (c != '*' && c != '/') {				inputPutback(ep, c);				tokenAddChar(ep, EJS_EXPR_DIV);				return EJS_TOK_EXPR;			}			style = c;			/*			 *	Eat comments. Both C and C++ comment styles are supported.			 */			while (1) {				if ((c = inputGetc(ep)) < 0) {					if (style == '/') {						return EJS_TOK_EOF;					}					ejsError(ep, "Syntax Error");					return EJS_TOK_ERR;				}				if (c == '\n' && style == '/') {					break;				} else if (c == '*') {					c = inputGetc(ep);					if (style == '/') {						if (c == '\n') {							break;						}					} else {						if (c == '/') {							break;						}

⌨️ 快捷键说明

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