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); readToken (token); } else if ( isType (token, TOKEN_OPEN_PAREN) ) { skipArgumentList(token); } else { readToken (token); } } }
static boolean findCmdTerm (tokenInfo *const token, boolean include_newlines) { /* * 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) && ! isType (token, TOKEN_EOF)) { /* Handle nested blocks */ if ( isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, token); readTokenFull (token, include_newlines, NULL); } else if ( isType (token, TOKEN_OPEN_PAREN) ) { skipArgumentList(token, include_newlines, NULL); } else if ( isType (token, TOKEN_OPEN_SQUARE) ) { skipArrayList(token, include_newlines); } else { readTokenFull (token, include_newlines, NULL); } } return isType (token, TOKEN_SEMICOLON); }
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, FALSE, NULL); } if (isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, token); } }
static void parseSubProgram (tokenInfo *const token) { tokenInfo *const name = newToken (); const sqlKind kind = isKeyword (token, KEYWORD_function) ? SQLTAG_FUNCTION : SQLTAG_PROCEDURE; Assert (isKeyword (token, KEYWORD_function) || isKeyword (token, KEYWORD_procedure)); readToken (name); readToken (token); skipArgumentList (token); if (isKeyword (token, KEYWORD_return)) { do readToken (token); /* read return type */ while (!(isKeyword (token, KEYWORD_is) || isType (token, TOKEN_SEMICOLON))); } if (isKeyword (token, KEYWORD_is)) { if (isType (name, TOKEN_IDENTIFIER)) makeSqlTag (name, kind); parseBlock (token, TRUE); } else if (isType (token, TOKEN_SEMICOLON)) makeSqlTag (name, SQLTAG_PROTOTYPE); deleteToken (name); }
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)) { skipArgumentList(token, FALSE, NULL); } if (isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, token); } }
static void parseFunction (tokenInfo *const token) { tokenInfo *const name = newToken (); vString *const signature = vStringNew (); boolean is_class = FALSE; /* * This deals with these formats * function validFunctionTwo(a,b) {} */ readToken (name); if (!isType (name, TOKEN_IDENTIFIER)) goto cleanUp; /* Add scope in case this is an INNER function */ addToScope(name, token->scope); readToken (token); while (isType (token, TOKEN_PERIOD)) { readToken (token); if ( isKeyword(token, KEYWORD_NONE) ) { addContext (name, token); readToken (token); } } if ( isType (token, TOKEN_OPEN_PAREN) ) skipArgumentList(token, FALSE, signature); if ( isType (token, TOKEN_OPEN_CURLY) ) { is_class = parseBlock (token, name); if ( is_class ) makeClassTag (name, signature); else makeFunctionTag (name, signature); } findCmdTerm (token, FALSE, FALSE); cleanUp: vStringDelete (signature); deleteToken (name); }
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 boolean parseIf (tokenInfo *const token) { boolean read_next_token = TRUE; /* * If statements have two forms * if ( ... ) * one line; * * if ( ... ) * statement; * else * statement * * if ( ... ) { * multiple; * statements; * } * * * if ( ... ) { * return elem * } * * This example if correctly written, but the * else contains only 1 statement without a terminator * since the function finishes with the closing brace. * * function a(flag){ * if(flag) * test(1); * else * test(2) * } * * 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 (isKeyword (token, KEYWORD_if)) { /* * Check for an "else if" and consume the "if" */ 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); /* The next token should only be read if this statement had its own * terminator */ read_next_token = isType (token, TOKEN_SEMICOLON); } return read_next_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 boolean parseIf (tokenInfo *const token, tokenInfo *const parent) { boolean read_next_token = TRUE; /* * If statements have two forms * if ( ... ) * one line; * * if ( ... ) * statement; * else * statement * * if ( ... ) { * multiple; * statements; * } * * * if ( ... ) { * return elem * } * * This example if correctly written, but the * else contains only 1 statement without a terminator * since the function finishes with the closing brace. * * function a(flag){ * if(flag) * test(1); * else * test(2) * } * * 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 (isKeyword (token, KEYWORD_if)) { /* * Check for an "else if" and consume the "if" */ readToken (token); } if (isType (token, TOKEN_OPEN_PAREN)) { skipArgumentList(token, FALSE, NULL); } if (isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, parent); } else { /* The next token should only be read if this statement had its own * terminator */ read_next_token = findCmdTerm (token, TRUE, FALSE); } return read_next_token; }
static boolean parseLoop (tokenInfo *const token, tokenInfo *const parent) { /* * 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); */ boolean is_terminated = TRUE; if (isKeyword (token, KEYWORD_for) || isKeyword (token, KEYWORD_while)) { readToken(token); if (isType (token, TOKEN_OPEN_PAREN)) { skipArgumentList(token, FALSE, NULL); } if (isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, parent); } else { is_terminated = parseLine(token, parent, FALSE); } } else if (isKeyword (token, KEYWORD_do)) { readToken(token); if (isType (token, TOKEN_OPEN_CURLY)) { parseBlock (token, parent); } else { is_terminated = parseLine(token, parent, FALSE); } if (is_terminated) readToken(token); if (isKeyword (token, KEYWORD_while)) { readToken(token); if (isType (token, TOKEN_OPEN_PAREN)) { skipArgumentList(token, TRUE, NULL); } if (! isType (token, TOKEN_SEMICOLON)) is_terminated = FALSE; } } return is_terminated; }