summaryrefslogtreecommitdiff
path: root/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/ejs/ejsLex.c')
-rw-r--r--source4/lib/appweb/ejs-2.0/ejs/ejsLex.c1033
1 files changed, 0 insertions, 1033 deletions
diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c b/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c
deleted file mode 100644
index fbfee6e4d5..0000000000
--- a/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c
+++ /dev/null
@@ -1,1033 +0,0 @@
-/*
- * @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-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 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);
-static void parseNumber(Ejs *ep, EjsType type);
-
-/************************************* Code ***********************************/
-/*
- * Open a new input script
- */
-
-int ejsLexOpenScript(Ejs *ep, const char *script)
-{
- EjsInput *ip;
-
- mprAssert(ep);
- mprAssert(script);
-
- if ((ip = mprAllocTypeZeroed(ep, EjsInput)) == NULL) {
- return MPR_ERR_MEMORY;
- }
- ip->next = ep->input;
- ep->input = ip;
- ip->procName = ep->proc ? ep->proc->procName : NULL;
- ip->fileName = ep->fileName ? ep->fileName : NULL;
-
-/*
- * Create the parse token buffer and script buffer
- */
- ip->tokServp = ip->tokbuf;
- ip->tokEndp = ip->tokbuf;
-
- ip->script = script;
- ip->scriptSize = strlen(script);
- ip->scriptServp = (char*) ip->script;
-
- ip->lineNumber = 1;
- ip->lineColumn = 0;
-
- ip->putBackIndex = -1;
-
- return 0;
-}
-
-/******************************************************************************/
-/*
- * Close the input script
- */
-
-void ejsLexCloseScript(Ejs *ep)
-{
- EjsInput *ip;
-
- mprAssert(ep);
-
- ip = ep->input;
- mprAssert(ip);
- ep->input = ip->next;
-
- 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++) {
- mprStrcpy(state->putBack[i].tokbuf, EJS_MAX_TOKEN,
- ip->putBack[i].tokbuf);
- state->putBack[i].tid = ip->putBack[i].tid;
- }
-
- mprStrcpy(state->line, sizeof(state->line), ip->line);
-
- state->lineColumn = ip->lineColumn;
- state->lineNumber = ip->lineNumber;
-}
-
-/******************************************************************************/
-/*
- * Restore the input state
- */
-
-void ejsLexRestoreInputState(Ejs *ep, EjsInput *state)
-{
- EjsInput *ip;
- EjsToken *tp;
- int i;
-
- mprAssert(ep);
- mprAssert(state);
-
- ip = ep->input;
- mprAssert(ip);
-
- mprStrcpy(ip->tokbuf, sizeof(ip->tokbuf), state->tokbuf);
- ip->tokServp = state->tokServp;
- ip->tokEndp = state->tokEndp;
-
- ip->script = state->script;
- ip->scriptServp = state->scriptServp;
- ip->scriptSize = state->scriptSize;
-
- ip->putBackIndex = state->putBackIndex;
- for (i = 0; i <= ip->putBackIndex; i++) {
- tp = &ip->putBack[i];
- tp->tid = state->putBack[i].tid;
- mprStrcpy(tp->tokbuf, sizeof(tp->tokbuf), state->putBack[i].tokbuf);
- }
-
- mprStrcpy(ip->line, sizeof(ip->line), state->line);
-
- ip->lineColumn = state->lineColumn;
- ip->lineNumber = state->lineNumber;
-}
-
-/******************************************************************************/
-/*
- * Free a saved input state
- */
-
-void ejsLexFreeInputState(Ejs *ep, EjsInput *state)
-{
- mprAssert(ep);
- mprAssert(state);
-
- state->putBackIndex = -1;
- 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", "delete", "function",
- * "class", "extends", "public", "private", "protected", "try", "catch",
- * "finally", "throw", "return", "get", "set", "this", "module", "each"
- *
- * The "new" and "in" reserved words are handled below. The "true", "false",
- * "null" "typeof" and "undefined" reserved words are handled as global
- * objects.
- *
- * Other reserved words not supported:
- * "break", "case", "continue", "default", "do",
- * "instanceof", "switch", "while", "with"
- *
- * ECMA extensions reserved words (not supported):
- * "abstract", "boolean", "byte", "char", "const",
- * "debugger", "double", "enum", "export",
- * "final", "float", "goto", "implements", "import", "int",
- * "interface", "long", "native", "package",
- * "short", "static", "super", "synchronized", "transient", "volatile"
- *
- * FUTURE -- use a hash lookup
- */
-
-static int checkReservedWord(Ejs *ep, int state, int c, int tid)
-{
- /* FUTURE -- probably should return for all tokens != EJS_TOK_ID */
- /* FUTURE -- Should have a hash for this. MUCH faster. */
-
- if (!isalpha(ep->token[0]) || tid == EJS_TOK_LITERAL) {
- return tid;
- }
- if (state == EJS_STATE_STMT) {
- /* FUTURE OPT -- convert to hash lookup */
- 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, "new") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_NEW;
- } 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, "class") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_CLASS;
- } else if (strcmp(ep->token, "module") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_MODULE;
- } else if (strcmp(ep->token, "extends") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_EXTENDS;
- } else if (strcmp(ep->token, "try") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_TRY;
- } else if (strcmp(ep->token, "catch") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_CATCH;
- } else if (strcmp(ep->token, "finally") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_FINALLY;
- } else if (strcmp(ep->token, "throw") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_THROW;
- } else if (strcmp(ep->token, "public") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_PUBLIC;
- } else if (strcmp(ep->token, "protected") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_PROTECTED;
- } else if (strcmp(ep->token, "private") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_PRIVATE;
- } else if (strcmp(ep->token, "get") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_GET;
- } else if (strcmp(ep->token, "set") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_SET;
- } else if (strcmp(ep->token, "extends") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_EXTENDS;
- } else if (strcmp(ep->token, "try") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_TRY;
- } else if (strcmp(ep->token, "catch") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_CATCH;
- } else if (strcmp(ep->token, "finally") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_FINALLY;
- } else if (strcmp(ep->token, "throw") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_THROW;
- } else if (strcmp(ep->token, "public") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_PUBLIC;
- } else if (strcmp(ep->token, "protected") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_PROTECTED;
- } else if (strcmp(ep->token, "private") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_PRIVATE;
- } else if (strcmp(ep->token, "get") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_GET;
- } else if (strcmp(ep->token, "set") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_SET;
- } else if (strcmp(ep->token, "each") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_EACH;
- } 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;
- }
-
- } else if (state == EJS_STATE_DEC) {
- if (strcmp(ep->token, "extends") == 0) {
- inputPutback(ep, c);
- return EJS_TOK_EXTENDS;
- }
- }
- return tid;
-}
-
-/******************************************************************************/
-/*
- * Get the next EJS token
- */
-
-static int getLexicalToken(Ejs *ep, int state)
-{
- EjsType type;
- EjsInput *ip;
- int done, tid, c, quote, style, idx, isHex;
-
- mprAssert(ep);
- ip = ep->input;
- mprAssert(ip);
-
- ep->tid = -1;
- tid = -1;
- type = BLD_FEATURE_NUM_TYPE_ID;
- isHex = 0;
-
- /*
- * Use a putback tokens first. Don't free strings as caller needs access.
- */
- if (ip->putBackIndex >= 0) {
- idx = ip->putBackIndex;
- tid = ip->putBack[idx].tid;
- ep->token = (char*) ip->putBack[idx].tokbuf;
- 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) {
- ejsSyntaxError(ep, 0);
- 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) {
- ejsSyntaxError(ep, 0);
- 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) {
- ejsSyntaxError(ep, 0);
- 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;
- }
- ejsSyntaxError(ep, 0);
- 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;
- }
- }
- }
- }
- /*
- * Continue looking for a token, so get the next character
- */
- if ((c = inputGetc(ep)) < 0) {
- return EJS_TOK_EOF;
- }
- break;
-
- case '<': /* < and <= */
- if ((c = inputGetc(ep)) < 0) {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
- if (c == '<') {
- tokenAddChar(ep, EJS_EXPR_LSHIFT);
- return EJS_TOK_EXPR;
- } else if (c == '=') {
- tokenAddChar(ep, EJS_EXPR_LESSEQ);
- return EJS_TOK_EXPR;
- }
- tokenAddChar(ep, EJS_EXPR_LESS);
- inputPutback(ep, c);
- return EJS_TOK_EXPR;
-
- case '>': /* > and >= */
- if ((c = inputGetc(ep)) < 0) {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
- if (c == '>') {
- tokenAddChar(ep, EJS_EXPR_RSHIFT);
- return EJS_TOK_EXPR;
- } else if (c == '=') {
- tokenAddChar(ep, EJS_EXPR_GREATEREQ);
- return EJS_TOK_EXPR;
- }
- tokenAddChar(ep, EJS_EXPR_GREATER);
- inputPutback(ep, c);
- return EJS_TOK_EXPR;
-
- case '=': /* "==" */
- if ((c = inputGetc(ep)) < 0) {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
- if (c == '=') {
- tokenAddChar(ep, EJS_EXPR_EQ);
- return EJS_TOK_EXPR;
- }
- inputPutback(ep, c);
- return EJS_TOK_ASSIGNMENT;
-
- case '!': /* "!=" or "!"*/
- if ((c = inputGetc(ep)) < 0) {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
- if (c == '=') {
- tokenAddChar(ep, EJS_EXPR_NOTEQ);
- return EJS_TOK_EXPR;
- }
- inputPutback(ep, c);
- tokenAddChar(ep, EJS_EXPR_BOOL_COMP);
- return EJS_TOK_EXPR;
-
- case ';':
- tokenAddChar(ep, c);
- return EJS_TOK_SEMI;
-
- case ',':
- tokenAddChar(ep, c);
- return EJS_TOK_COMMA;
-
- case ':':
- tokenAddChar(ep, c);
- return EJS_TOK_COLON;
-
- case '|': /* "||" */
- if ((c = inputGetc(ep)) < 0 || c != '|') {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
- tokenAddChar(ep, EJS_COND_OR);
- return EJS_TOK_LOGICAL;
-
- case '&': /* "&&" */
- if ((c = inputGetc(ep)) < 0 || c != '&') {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
- tokenAddChar(ep, EJS_COND_AND);
- return EJS_TOK_LOGICAL;
-
- case '\"': /* String quote */
- case '\'':
- quote = c;
- if ((c = inputGetc(ep)) < 0) {
- ejsSyntaxError(ep, 0);
- return EJS_TOK_ERR;
- }
-
- while (c != quote) {
- /*
- * Check for escape sequence characters
- */
- if (c == '\\') {
- c = inputGetc(ep);
-
- if (isdigit(c)) {
- /*
- * Octal support, \101 maps to 65 = 'A'. Put first
- * char back so converter will work properly.
- */
- inputPutback(ep, c);
- c = charConvert(ep, 8, 3);
-
- } else {
- switch (c) {
- case 'n':
- c = '\n'; break;
- case 'b':
- c = '\b'; break;
- case 'f':
- c = '\f'; break;
- case 'r':
- c = '\r'; break;
- case 't':
- c = '\t'; break;
- case 'x':
- /*
- * Hex support, \x41 maps to 65 = 'A'
- */
- c = charConvert(ep, 16, 2);
- break;
- case 'u':
- /*
- * Unicode support, \x0401 maps to 65 = 'A'
- */
- c = charConvert(ep, 16, 2);
- c = c*16 + charConvert(ep, 16, 2);
-
- break;
- case '\'':
- case '\"':
- case '\\':
- break;
- default:
- if (tokenAddChar(ep, '\\') < 0) {
- return EJS_TOK_ERR;
- }
- }
- }
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- } else {
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- }
- if ((c = inputGetc(ep)) < 0) {
- ejsSyntaxError(ep, "Unmatched Quote");
- return EJS_TOK_ERR;
- }
- }
- return EJS_TOK_LITERAL;
-
- case '0':
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- if (tolower(c) == 'x') {
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- isHex = 1;
- if (! isxdigit(c)) {
- parseNumber(ep, type);
- inputPutback(ep, c);
- return EJS_TOK_NUMBER;
- }
- } else if (! isdigit(c)) {
-#if BLD_FEATURE_FLOATING_POINT
- if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') {
- /* Fall through */
- type = EJS_TYPE_FLOAT;
- } else
-#endif
- {
- parseNumber(ep, type);
- inputPutback(ep, c);
- return EJS_TOK_NUMBER;
- }
- }
- /* Fall through to get more digits */
-
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (isHex) {
- do {
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- } while (isxdigit(c));
-
- } else {
-#if BLD_FEATURE_FLOATING_POINT
- do {
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- c = tolower(c);
- if (c == '.' || c == 'e' || c == 'f') {
- type = EJS_TYPE_FLOAT;
- }
- } while (isdigit(c) || c == '.' || c == 'e' ||
- c == 'f' ||
- ((type == EJS_TYPE_FLOAT) && (c == '+' || c == '-')));
-#else
- do {
- if (tokenAddChar(ep, c) < 0) {
- return EJS_TOK_ERR;
- }
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- } while (isdigit(c));
-#endif
- }
-
- parseNumber(ep, type);
- inputPutback(ep, c);
- return EJS_TOK_NUMBER;
-
- default:
- /*
- * Identifiers or a function names
- */
- while (1) {
- if (c == '\\') {
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- if (c == '\n' || c == '\r') {
- break;
- }
- } else if (tokenAddChar(ep, c) < 0) {
- break;
- }
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- if (!isalnum(c) && c != '$' && c != '_' &&
- c != '\\' && c != '@') {
- break;
- }
- }
- if (*ep->token == '\0') {
- c = inputGetc(ep);
- break;
- }
-
- if (! isalpha((int) *ep->token) && *ep->token != '$' &&
- *ep->token != '_' && *ep->token != '@') {
- ejsError(ep, EJS_SYNTAX_ERROR, "Invalid identifier %s",
- ep->token);
- return EJS_TOK_ERR;
- }
-
- tid = checkReservedWord(ep, state, c, EJS_TOK_ID);
- if (tid != EJS_TOK_ID) {
- return tid;
- }
-
- /*
- * Skip white space after token to find out whether this is
- * a function or not.
- */
- while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
- if ((c = inputGetc(ep)) < 0)
- break;
- }
-
- tid = EJS_TOK_ID;
- if ((strlen(ep->token) + 1) >= EJS_MAX_ID) {
- ejsError(ep, EJS_SYNTAX_ERROR,
- "Identifier too big. Max is %d letters.", EJS_MAX_ID);
- return EJS_TOK_ERR;
- }
- done++;
- }
- }
-
- /*
- * Putback the last extra character for next time
- */
- inputPutback(ep, c);
- return tid;
-}
-
-/******************************************************************************/
-
-static void parseNumber(Ejs *ep, EjsType type)
-{
- switch (type) {
- case EJS_TYPE_INT:
- ep->tokenNumber.integer = ejsParseInteger(ep->token);
- ep->tokenNumber.type = type;
- break;
-
-#if BLD_FEATURE_FLOATING_POINT
- case EJS_TYPE_FLOAT:
- ep->tokenNumber.floating = atof(ep->token);
- ep->tokenNumber.type = type;
- break;
-#endif
-
-#if BLD_FEATURE_INT64
- case EJS_TYPE_INT64:
- ep->tokenNumber.integer64 = ejsParseInteger64(ep->token);
- ep->tokenNumber.type = type;
- break;
-#endif
- }
-}
-
-/******************************************************************************/
-/*
- * Convert a hex or octal character back to binary, return original char if
- * not a hex digit
- */
-
-static int charConvert(Ejs *ep, int base, int maxDig)
-{
- int i, c, lval, convChar;
-
- lval = 0;
- for (i = 0; i < maxDig; i++) {
- if ((c = inputGetc(ep)) < 0) {
- break;
- }
- /*
- * Initialize to out of range value
- */
- convChar = base;
- if (isdigit(c)) {
- convChar = c - '0';
- } else if (c >= 'a' && c <= 'f') {
- convChar = c - 'a' + 10;
- } else if (c >= 'A' && c <= 'F') {
- convChar = c - 'A' + 10;
- }
- /*
- * If unexpected character then return it to buffer.
- */
- if (convChar >= base) {
- inputPutback(ep, c);
- break;
- }
- lval = (lval * base) + convChar;
- }
- return lval;
-}
-
-/******************************************************************************/
-/*
- * Putback the last token read. Accept at most one push back token.
- */
-
-void ejsLexPutbackToken(Ejs *ep, int tid, char *string)
-{
- EjsInput *ip;
- EjsToken *tp;
- int idx;
-
- mprAssert(ep);
- ip = ep->input;
- mprAssert(ip);
-
- ip->putBackIndex += 1;
-
- mprAssert(ip->putBackIndex < EJS_TOKEN_STACK);
- idx = ip->putBackIndex;
-
- tp = &ip->putBack[idx];
- tp->tid = tid;
-
- mprStrcpy(tp->tokbuf, sizeof(tp->tokbuf), string);
-}
-
-/******************************************************************************/
-/*
- * Add a character to the token buffer
- */
-
-static int tokenAddChar(Ejs *ep, int c)
-{
- EjsInput *ip;
-
- mprAssert(ep);
- ip = ep->input;
- mprAssert(ip);
-
- if (ip->tokEndp >= &ip->tokbuf[sizeof(ip->tokbuf) - 1]) {
- ejsSyntaxError(ep, "Token too big");
- return -1;
- }
- *ip->tokEndp++ = c;
- *ip->tokEndp = '\0';
-
- return 0;
-}
-
-/******************************************************************************/
-/*
- * Get another input character
- */
-
-static int inputGetc(Ejs *ep)
-{
- EjsInput *ip;
- int c;
-
- mprAssert(ep);
- ip = ep->input;
-
- if (ip->scriptSize <= 0) {
- return -1;
- }
-
- c = (uchar) (*ip->scriptServp++);
- ip->scriptSize--;
-
- /*
- * For debugging, accumulate the line number and the currenly parsed line
- */
- if (c == '\n') {
-#if 0 && BLD_DEBUG
- if (ip->lineColumn > 0) {
- printf("PARSED: %s\n", ip->line);
- }
-#endif
- ip->lineNumber++;
- ip->lineColumn = 0;
- } else if ((ip->lineColumn + 2) < sizeof(ip->line)) {
- ip->line[ip->lineColumn++] = c;
- ip->line[ip->lineColumn] = '\0';
- }
- return c;
-}
-
-/******************************************************************************/
-/*
- * Putback a character onto the input queue
- */
-
-static void inputPutback(Ejs *ep, int c)
-{
- EjsInput *ip;
-
- mprAssert(ep);
-
- if (c > 0) {
- ip = ep->input;
- *--ip->scriptServp = c;
- ip->scriptSize++;
- if (--(ip->lineColumn) < 0) {
- ip->lineColumn = 0;
- }
- mprAssert(ip->line);
- mprAssert(ip->lineColumn >= 0);
- mprAssert(ip->lineColumn < sizeof(ip->line));
- ip->line[ip->lineColumn] = '\0';
- }
-}
-
-/******************************************************************************/
-
-#else
-void ejsLexDummy() {}
-
-/******************************************************************************/
-#endif /* BLD_FEATURE_EJS */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim:tw=78
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */