Token *Lexer::nextToken() { while(true) { switch(_currentChar.toAscii()) { case '\'': return scanCharacter(); case '"': return scanText(); case '(': return scan(Token::LeftParenthesis); case ')': return scan(Token::RightParenthesis); case '[': return scan(Token::LeftBracket); case ']': return scanRightBracket(); case '{': return scan(Token::LeftBrace); case '}': return scan(Token::RightBrace); case ';': return scan(Token::Semicolon); default: if(isEof()) return scan(Token::Eof); else if(isLineComment()) consumeLineComment(); else if(isBlockComment()) consumeBlockComment(); else if(isNewline()) return scanNewline(); else if(isSpace()) consumeSpaces(); else if(isName()) return scanName(); else if(isBackquotedName()) return scanBackquotedName(); else if(isNumber()) return scanNumber(); else if(isOperator()) return scanOperator(); else throw lexerException(QString("invalid character: '%1'").arg(_currentChar)); } } }
bool Scanner::scanName (char c, Parser& parser, bool& cont) { std::string name; name += c; if (!scanName (name)) return false; TokenLoc loc (mLoc); mLoc.mLiteral.clear(); if (name.size()>=2 && name[0]=='"' && name[name.size()-1]=='"') { name = name.substr (1, name.size()-2); // allow keywords enclosed in "" /// \todo optionally disable // cont = parser.parseName (name, loc, *this); // return true; } int i = 0; std::string lowerCase = Misc::StringUtils::lowerCase(name); for (; keywords[i]; ++i) if (lowerCase==keywords[i]) break; if (keywords[i]) { cont = parser.parseKeyword (i, loc, *this); return true; } if (mExtensions) { if (int keyword = mExtensions->searchKeyword (lowerCase)) { cont = parser.parseKeyword (keyword, loc, *this); return true; } } cont = parser.parseName (name, loc, *this); return true; }
void scanProcessingInstruction(void *data, const char *target, const char *text) { Scanner* self = data; xsMachine* the = self->the; scanText(data); scanName(the, target, 1); xsVar(VALUE) = xsString((xsStringValue)text); xsVar(LINE) = xsInteger(XML_GetCurrentLineNumber(self->expat)); xsVar(CHILD) = xsNewInstanceOf(xsVar(PI_PROTOTYPE)); xsSet(xsVar(CHILD), xsID_path, xsVar(PATH)); xsSet(xsVar(CHILD), xsID_line, xsVar(LINE)); xsSet(xsVar(CHILD), xsID_parent, xsResult); xsSet(xsVar(CHILD), xsID_name, xsVar(NAME)); xsSet(xsVar(CHILD), xsID_namespace, xsVar(NAMESPACE)); xsSet(xsVar(CHILD), xsID_prefix, xsVar(PREFIX)); xsSet(xsVar(CHILD), xsID_value, xsVar(VALUE)); xsArrayCacheItem(xsVar(CHILDREN), xsVar(CHILD)); }
bool Scanner::scanToken (Parser& parser) { switch (mPutback) { case Putback_Special: mPutback = Putback_None; return parser.parseSpecial (mPutbackCode, mPutbackLoc, *this); case Putback_Integer: mPutback = Putback_None; return parser.parseInt (mPutbackInteger, mPutbackLoc, *this); case Putback_Float: mPutback = Putback_None; return parser.parseFloat (mPutbackFloat, mPutbackLoc, *this); case Putback_Name: mPutback = Putback_None; return parser.parseName (mPutbackName, mPutbackLoc, *this); case Putback_Keyword: mPutback = Putback_None; return parser.parseKeyword (mPutbackCode, mPutbackLoc, *this); case Putback_None: break; } char c; if (!get (c)) { parser.parseEOF (*this); return false; } else if (c==';') { std::string comment; comment += c; while (get (c)) { if (c=='\n') { putback (c); break; } else comment += c; } TokenLoc loc (mLoc); mLoc.mLiteral.clear(); return parser.parseComment (comment, loc, *this); } else if (isWhitespace (c)) { mLoc.mLiteral.clear(); return true; } else if (c==':') { // treat : as a whitespace :( mLoc.mLiteral.clear(); return true; } else if (std::isalpha (c) || c=='_' || c=='"') { bool cont = false; if (scanName (c, parser, cont)) { mLoc.mLiteral.clear(); return cont; } } else if (std::isdigit (c)) { bool cont = false; if (scanInt (c, parser, cont)) { mLoc.mLiteral.clear(); return cont; } } else if (c==13) // linux compatibility hack { return true; } else { bool cont = false; if (scanSpecial (c, parser, cont)) { mLoc.mLiteral.clear(); return cont; } } TokenLoc loc (mLoc); mLoc.mLiteral.clear(); mErrorHandler.error ("syntax error", loc); throw SourceException(); }
bool Scanner::scanName (char c, Parser& parser, bool& cont) { std::string name; name += c; if (!scanName (name)) return false; TokenLoc loc (mLoc); mLoc.mLiteral.clear(); if (name.size()>=2 && name[0]=='"' && name[name.size()-1]=='"') { name = name.substr (1, name.size()-2); // allow keywords enclosed in "" /// \todo optionally disable if (mStrictKeywords) { cont = parser.parseName (name, loc, *this); return true; } } int i = 0; std::string lowerCase = Misc::StringUtils::lowerCase(name); bool isKeyword = false; for (; sKeywords[i]; ++i) if (lowerCase==sKeywords[i]) { isKeyword = true; break; } // Russian localization and some mods use a quirk - add newline character directly // to compiled bytecode via HEX-editor to implement multiline messageboxes. // Of course, original editor will not compile such script. // Allow messageboxes to bybass the "incomplete string or name" error. if (lowerCase == "messagebox") enableIgnoreNewlines(); else if (isKeyword) mIgnoreNewline = false; if (sKeywords[i]) { cont = parser.parseKeyword (i, loc, *this); return true; } if (mExtensions) { if (int keyword = mExtensions->searchKeyword (lowerCase)) { cont = parser.parseKeyword (keyword, loc, *this); return true; } } cont = parser.parseName (name, loc, *this); return true; }
void scanStartTag(void *data, const char *tag, const char **attributes) { Scanner* self = data; xsMachine* the = self->the; const char **attribute; char* name; char* value; char* colon; scanText(data); xsVar(LINE) = xsInteger(XML_GetCurrentLineNumber(self->expat)); xsVar(CHILD) = xsNewInstanceOf(xsVar(ELEMENT_PROTOTYPE)); xsSet(xsVar(CHILD), xsID_path, xsVar(PATH)); xsSet(xsVar(CHILD), xsID_line, xsVar(LINE)); xsSet(xsVar(CHILD), xsID_parent, xsResult); if (!self->root) { self->root = 1; xsSet(xsResult, xsID_element, xsVar(CHILD)); } xsArrayCacheItem(xsVar(CHILDREN), xsVar(CHILD)); xsResult = xsVar(CHILD); xsVar(CHILDREN) = xsNewInstanceOf(xsArrayPrototype); xsArrayCacheBegin(xsVar(CHILDREN)); attribute = attributes; while (*attribute) { name = (char*)*attribute; attribute++; value = (char*)*attribute; attribute++; if (c_strncmp(name, "xmlns", 5) == 0) { colon = name + 5; if (*colon == ':') { *colon = 0; xsVar(NAME) = xsString(colon + 1); *colon = ':'; xsVar(PREFIX) = xsVar(XML_PREFIX); } else { xsVar(NAME) = xsVar(XML_PREFIX); xsVar(PREFIX) = xsUndefined; } xsVar(NAMESPACE) = xsVar(XML_NAMESPACE); xsVar(VALUE) = xsString(value); xsVar(CHILD) = xsNewInstanceOf(xsVar(ATTRIBUTE_PROTOTYPE)); xsSet(xsVar(CHILD), xsID_parent, xsResult); xsSet(xsVar(CHILD), xsID_path, xsVar(PATH)); xsSet(xsVar(CHILD), xsID_line, xsVar(LINE)); xsSet(xsVar(CHILD), xsID_name, xsVar(NAME)); xsSet(xsVar(CHILD), xsID_namespace, xsVar(NAMESPACE)); xsSet(xsVar(CHILD), xsID_prefix, xsVar(PREFIX)); xsSet(xsVar(CHILD), xsID_value, xsVar(VALUE)); xsArrayCacheItem(xsVar(CHILDREN), xsVar(CHILD)); } } xsArrayCacheEnd(xsVar(CHILDREN)); xsSet(xsResult, xsID_xmlnsAttributes, xsVar(CHILDREN)); xsVar(CHILDREN) = xsNewInstanceOf(xsArrayPrototype); xsArrayCacheBegin(xsVar(CHILDREN)); attribute = attributes; while (*attribute) { name = (char*)*attribute; attribute++; value = (char*)*attribute; attribute++; if (c_strncmp(name, "xmlns", 5) != 0) { scanName(the, name, 0); xsVar(VALUE) = xsString(value); xsVar(CHILD) = xsNewInstanceOf(xsVar(ATTRIBUTE_PROTOTYPE)); xsSet(xsVar(CHILD), xsID_parent, xsResult); xsSet(xsVar(CHILD), xsID_path, xsVar(PATH)); xsSet(xsVar(CHILD), xsID_line, xsVar(LINE)); xsSet(xsVar(CHILD), xsID_name, xsVar(NAME)); xsSet(xsVar(CHILD), xsID_namespace, xsVar(NAMESPACE)); xsSet(xsVar(CHILD), xsID_prefix, xsVar(PREFIX)); xsSet(xsVar(CHILD), xsID_value, xsVar(VALUE)); xsArrayCacheItem(xsVar(CHILDREN), xsVar(CHILD)); } } xsArrayCacheEnd(xsVar(CHILDREN)); xsSet(xsResult, xsID__attributes, xsVar(CHILDREN)); scanName(the, tag, 1); xsSet(xsResult, xsID_name, xsVar(NAME)); xsSet(xsResult, xsID_namespace, xsVar(NAMESPACE)); xsSet(xsResult, xsID_prefix, xsVar(PREFIX)); xsVar(CHILDREN) = xsNewInstanceOf(xsArrayPrototype); xsArrayCacheBegin(xsVar(CHILDREN)); xsSet(xsResult, xsID_children, xsVar(CHILDREN)); }