123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /****************************************************************************
- Copyright (C) 2013 Henry van Merode. All rights reserved.
- Copyright (c) 2015-2016 Chukong Technologies Inc.
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
-
- http://www.cocos2d-x.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- #include "CCPUScriptLexer.h"
- NS_CC_BEGIN
- PUScriptLexer::PUScriptLexer()
- {
-
- }
- PUScriptLexer::~PUScriptLexer()
- {
-
- }
- void PUScriptLexer::openLexer(const std::string &str,const std::string &source,PUScriptTokenList& tokens)
- {
- enum{ READY = 0, COMMENT, MULTICOMMENT, WORD, QUOTE, VAR, POSSIBLECOMMENT };
-
- const wchar_t varopener = '$', quote = '\"', slash = '/', backslash = '\\', openbrace = '{', closebrace = '}', colon = ':', star = '*', cr = '\r', lf = '\n';
- char c = 0, lastc = 0;
-
-
- std::string lexeme;
- unsigned int line = 1, state = READY, lastQuote = 0;
-
- // ScriptTokenListPtr tokens(OGRE_NEW_T(ScriptTokenList, MEMCATEGORY_GENERAL)(), SPFM_DELETE_T);
- //
- // Iterate over the input
- std::string::const_iterator i = str.begin(), end = str.end();
- while(i != end)
- {
- lastc = c;
- c = *i;
-
- if(c == quote)
- lastQuote = line;
-
- switch(state)
- {
- case READY:
- if(c == slash && lastc == slash)
- {
- // Comment start, clear out the lexeme
- lexeme = "";
- state = COMMENT;
- }
- else if(c == star && lastc == slash)
- {
- lexeme = "";
- state = MULTICOMMENT;
- }
- else if(c == quote)
- {
- // Clear out the lexeme ready to be filled with quotes!
- lexeme = c;
- state = QUOTE;
- }
- else if(c == varopener)
- {
- // Set up to read in a variable
- lexeme = c;
- state = VAR;
- }
- else if(isNewline(c))
- {
- lexeme = c;
- setToken(lexeme, line, source, &tokens);
- }
- else if(!isWhitespace(c))
- {
- lexeme = c;
- if(c == slash)
- state = POSSIBLECOMMENT;
- else
- state = WORD;
- }
- break;
- case COMMENT:
- // This newline happens to be ignored automatically
- if(isNewline(c))
- state = READY;
- break;
- case MULTICOMMENT:
- if(c == slash && lastc == star)
- state = READY;
- break;
- case POSSIBLECOMMENT:
- if(c == slash && lastc == slash)
- {
- lexeme = "";
- state = COMMENT;
- break;
- }
- else if(c == star && lastc == slash)
- {
- lexeme = "";
- state = MULTICOMMENT;
- break;
- }
- else
- {
- state = WORD;
- }
- case WORD:
- if(isNewline(c))
- {
- setToken(lexeme, line, source, &tokens);
- lexeme = c;
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else if(isWhitespace(c))
- {
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else if(c == openbrace || c == closebrace || c == colon)
- {
- setToken(lexeme, line, source, &tokens);
- lexeme = c;
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else
- {
- lexeme += c;
- }
- break;
- case QUOTE:
- if(c != backslash)
- {
- // Allow embedded quotes with escaping
- if(c == quote && lastc == backslash)
- {
- lexeme += c;
- }
- else if(c == quote)
- {
- lexeme += c;
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else
- {
- // Backtrack here and allow a backslash normally within the quote
- if(lastc == backslash)
- lexeme = lexeme + "\\" + c;
- else
- lexeme += c;
- }
- }
- break;
- case VAR:
- if(isNewline(c))
- {
- setToken(lexeme, line, source, &tokens);
- lexeme = c;
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else if(isWhitespace(c))
- {
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else if(c == openbrace || c == closebrace || c == colon)
- {
- setToken(lexeme, line, source, &tokens);
- lexeme = c;
- setToken(lexeme, line, source, &tokens);
- state = READY;
- }
- else
- {
- lexeme += c;
- }
- break;
- }
-
- // Separate check for newlines just to track line numbers
- if(c == cr || (c == lf && lastc != cr))
- line++;
-
- ++i;
- }
-
- // Check for valid exit states
- if(state == WORD || state == VAR)
- {
- if(!lexeme.empty())
- setToken(lexeme, line, source, &tokens);
- }
- else
- {
- if(state == QUOTE)
- {
- printf("Exception\n");
-
- // OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
- // Ogre::String("no matching \" found for \" at line ") +
- // Ogre::StringConverter::toString(lastQuote),
- // "ScriptLexer::tokenize");
- }
- }
-
- }
-
- void PUScriptLexer::setToken(const std::string &lexeme, int line, const std::string &source, PUScriptTokenList *tokens)
- {
-
- const char openBracket = '{', closeBracket = '}', colon = ':',
- quote = '\"', var = '$';
- PUScriptToken* token = new (std::nothrow) PUScriptToken;
-
- token->lexeme = lexeme;
- token->line = line;
- token->file = source;
- bool ignore = false;
-
- // Check the user token map first
- if(lexeme.size() == 1 && isNewline(lexeme[0]))
- {
- token->type = TID_NEWLINE;
- if(!tokens->empty() && tokens->back()->type == TID_NEWLINE){
- ignore = true;
- delete token;
- }
- }
- else if(lexeme.size() == 1 && lexeme[0] == openBracket)
- token->type = TID_LBRACKET;
- else if(lexeme.size() == 1 && lexeme[0] == closeBracket)
- token->type = TID_RBRACKET;
- else if(lexeme.size() == 1 && lexeme[0] == colon)
- token->type = TID_COLON;
- else if(lexeme[0] == var)
- token->type = TID_VARIABLE;
- else
- {
- // This is either a non-zero length phrase or quoted phrase
- if(lexeme.size() >= 2 && lexeme[0] == quote && lexeme[lexeme.size() - 1] == quote)
- {
- token->type = TID_QUOTE;
- }
- else
- {
- token->type = TID_WORD;
- }
- }
-
- if(!ignore)
- tokens->push_back(token);
- }
-
- bool PUScriptLexer::isWhitespace(char c) const
- {
- return c == ' ' || c == '\r' || c == '\t';
- }
-
- bool PUScriptLexer::isNewline(char c) const
- {
- return c == '\n' || c == '\r';
- }
- NS_CC_END
|