📄 jscript.c
字号:
static void skipArrayList (tokenInfo *const token){ int nest_level = 0; /* * Handle square brackets * var name[1] * So we must check for nested open and closing square brackets */ if (isType (token, TOKEN_OPEN_SQUARE)) /* arguments? */ { nest_level++; while (! (isType (token, TOKEN_CLOSE_SQUARE) && (nest_level == 0))) { readToken (token); if (isType (token, TOKEN_OPEN_SQUARE)) { nest_level++; } if (isType (token, TOKEN_CLOSE_SQUARE)) { if (nest_level > 0) { nest_level--; } } } readToken (token); }}static void addContext (tokenInfo* const parent, const tokenInfo* const child){ if (vStringLength (parent->string) > 0) { vStringCatS (parent->string, "."); } vStringCatS (parent->string, vStringValue(child->string)); vStringTerminate(parent->string);}static void addToScope (tokenInfo* const token, vString* const extra){ if (vStringLength (token->scope) > 0) { vStringCatS (token->scope, "."); } vStringCatS (token->scope, vStringValue(extra)); vStringTerminate(token->scope);}/* * Scanning functions */static void findCmdTerm (tokenInfo *const token){ /* * Read until we find either a semicolon or closing brace. * Any nested braces will be handled within. */ while (! ( isType (token, TOKEN_SEMICOLON) || isType (token, TOKEN_CLOSE_CURLY) ) ) { /* Handle nested blocks */ if ( isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, token); } else if ( isType (token, TOKEN_OPEN_PAREN) ) { skipArgumentList(token); } else { readToken (token); } } }static void parseSwitch (tokenInfo *const token){ /* * switch (expression){ * case value1: * statement; * break; * case value2: * statement; * break; * default : statement; * } */ readToken (token); if (isType (token, TOKEN_OPEN_PAREN)) { /* * Handle nameless functions, these will only * be considered methods. */ skipArgumentList(token); } if (isType (token, TOKEN_OPEN_CURLY)) { /* * This will be either a function or a class. * We can only determine this by checking the body * of the function. If we find a "this." we know * it is a class, otherwise it is a function. */ parseBlock (token, token); }}static void parseLoop (tokenInfo *const token){ /* * Handles these statements * for (x=0; x<3; x++) * document.write("This text is repeated three times<br>"); * * for (x=0; x<3; x++) * { * document.write("This text is repeated three times<br>"); * } * * while (number<5){ * document.write(number+"<br>"); * number++; * } * * do{ * document.write(number+"<br>"); * number++; * } * while (number<5); */ if (isKeyword (token, KEYWORD_for) || isKeyword (token, KEYWORD_while)) { readToken(token); if (isType (token, TOKEN_OPEN_PAREN)) { /* * Handle nameless functions, these will only * be considered methods. */ skipArgumentList(token); } if (isType (token, TOKEN_OPEN_CURLY)) { /* * This will be either a function or a class. * We can only determine this by checking the body * of the function. If we find a "this." we know * it is a class, otherwise it is a function. */ parseBlock (token, token); } else { parseLine(token, FALSE); } } else if (isKeyword (token, KEYWORD_do)) { readToken(token); if (isType (token, TOKEN_OPEN_CURLY)) { /* * This will be either a function or a class. * We can only determine this by checking the body * of the function. If we find a "this." we know * it is a class, otherwise it is a function. */ parseBlock (token, token); } else { parseLine(token, FALSE); } readToken(token); if (isKeyword (token, KEYWORD_while)) { readToken(token); if (isType (token, TOKEN_OPEN_PAREN)) { /* * Handle nameless functions, these will only * be considered methods. */ skipArgumentList(token); } } }}static void parseIf (tokenInfo *const token){ /* * If statements have two forms * if ( ... ) * one line; * * if ( ... ) { * multiple; * statements; * } * * if ( ... ) { * return elem * } * * TODO: Deal with statements that can optional end * without a semi-colon. Currently this messes up * the parsing of blocks. * Need to somehow detect this has happened, and either * backup a token, or skip reading the next token if * that is possible from all code locations. * */ readToken (token); if (isType (token, TOKEN_OPEN_PAREN)) { /* * Handle nameless functions, these will only * be considered methods. */ skipArgumentList(token); } if (isType (token, TOKEN_OPEN_CURLY)) { /* * This will be either a function or a class. * We can only determine this by checking the body * of the function. If we find a "this." we know * it is a class, otherwise it is a function. */ parseBlock (token, token); } else { findCmdTerm (token); }}static void parseFunction (tokenInfo *const token){ tokenInfo *const name = newToken (); boolean is_class = FALSE; /* * This deals with these formats * function validFunctionTwo(a,b) {} */ readToken (name); /* Add scope in case this is an INNER function */ addToScope(name, token->scope); readToken (token); if (isType (token, TOKEN_PERIOD)) { do { readToken (token); if ( isKeyword(token, KEYWORD_NONE) ) { addContext (name, token); readToken (token); } } while (isType (token, TOKEN_PERIOD)); } if ( isType (token, TOKEN_OPEN_PAREN) ) skipArgumentList(token); if ( isType (token, TOKEN_OPEN_CURLY) ) { is_class = parseBlock (token, name); if ( is_class ) makeClassTag (name); else makeFunctionTag (name); } findCmdTerm (token); deleteToken (name);}static boolean parseBlock (tokenInfo *const token, tokenInfo *const parent){ boolean is_class = FALSE; boolean read_next_token = TRUE; vString * saveScope = vStringNew (); token->nestLevel++; /* * Make this routine a bit more forgiving. * If called on an open_curly advance it */ if ( isType (token, TOKEN_OPEN_CURLY) && isKeyword(token, KEYWORD_NONE) ) readToken(token); if (! isType (token, TOKEN_CLOSE_CURLY)) { /* * Read until we find the closing brace, * any nested braces will be handled within */ do { read_next_token = TRUE; if (isKeyword (token, KEYWORD_this)) { /* * Means we are inside a class and have found * a class, not a function */ is_class = TRUE; vStringCopy(saveScope, token->scope); addToScope (token, parent->string); /* * Ignore the remainder of the line * findCmdTerm(token); */ parseLine (token, is_class); vStringCopy(token->scope, saveScope); } else if (isKeyword (token, KEYWORD_var)) { /* * Potentially we have found an inner function. * Set something to indicate the scope */ vStringCopy(saveScope, token->scope); addToScope (token, parent->string); parseLine (token, is_class); vStringCopy(token->scope, saveScope); } else if (isKeyword (token, KEYWORD_function)) { vStringCopy(saveScope, token->scope); addToScope (token, parent->string); parseFunction (token); vStringCopy(token->scope, saveScope); } else if (isType (token, TOKEN_OPEN_CURLY)) { /* Handle nested blocks */ parseBlock (token, parent); } else { /* * It is possible for a line to have no terminator * if the following line is a closing brace. * parseLine will detect this case and indicate * whether we should read an additional token. */ read_next_token = parseLine (token, is_class); } /* * Always read a new token unless we find a statement without * a ending terminator */ if( read_next_token ) readToken(token); /* * If we find a statement without a terminator consider the * block finished, otherwise the stack will be off by one. */ } while (! isType (token, TOKEN_CLOSE_CURLY) && read_next_token ); } vStringDelete(saveScope); token->nestLevel--; return is_class;}static void parseMethods (tokenInfo *const token, tokenInfo *const class){ tokenInfo *const name = newToken (); /* * This deals with these formats * 'validMethod' : function(a,b) {} */ do { readToken (token); if (isType (token, TOKEN_STRING)) { copyToken(name, token); readToken (token); if ( isType (token, TOKEN_COLON) ) { readToken (token); if ( isKeyword (token, KEYWORD_function) ) { readToken (token); if ( isType (token, TOKEN_OPEN_PAREN) ) { skipArgumentList(token); } if (isType (token, TOKEN_OPEN_CURLY)) { addToScope (name, class->string); makeJsTag (name, JSTAG_METHOD); parseBlock (token, name); /* * Read to the closing curly, check next * token, if comma, we must loop again */ readToken (token); } } } } } while ( isType(token, TOKEN_COMMA) ); findCmdTerm (token); deleteToken (name);}static boolean parseStatement (tokenInfo *const token, boolean is_inside_class){ tokenInfo *const name = newToken (); tokenInfo *const secondary_name = newToken (); vString * saveScope = vStringNew (); boolean is_class = FALSE; boolean is_terminated = TRUE; boolean is_global = FALSE; boolean is_prototype = FALSE; vStringClear(saveScope); /* * Functions can be named or unnamed. * This deals with these formats: * Function * validFunctionOne = function(a,b) {} * testlib.validFunctionFive = function(a,b) {} * var innerThree = function(a,b) {} * var innerFour = (a,b) {} * var D2 = secondary_fcn_name(a,b) {} * var D3 = new Function("a", "b", "return a+b;"); * Class * testlib.extras.ValidClassOne = function(a,b) { * this.a = a; * } * Class Methods * testlib.extras.ValidClassOne.prototype = { * 'validMethodOne' : function(a,b) {}, * 'validMethodTwo' : function(a,b) {} * } * ValidClassTwo = function () * { * this.validMethodThree = function() {} * // unnamed method * this.validMethodFour = () {} * } * Database.prototype.validMethodThree = Database_getTodaysDate;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -