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 + -
显示快捷键?