/* * This file is part of the Colobot: Gold Edition source code * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://gnu.org/licenses */ #pragma once #include "CBot/CBotEnums.h" #include "CBot/CBotUtils.h" #include #include #include #include /** * \brief Class representing one token of a program. * * A CBot program starts as a text string. This string is first transformed into a list of tokens. * * \section Tokens Example tokens * This code: * \code * int var = 3 * ( pos.y + x ); * string test = "Hello world"; * \endcode * * Is decomposed into (each line is a token, separate CBotToken instance): * \code * int * var * = * 3 * * * ( * pos * . * y * + * x * ) * ; * string * test * = * "Hello world" * ; * \endcode * * \section Usage Example usage * \code * std::unique_ptr tokens = CBotToken::CompileTokens(program); * CBotToken* token = tokens.get(); * while(token != nullptr) * { * printf("%s\n", token->GetString()); * * token = token->GetNext(); * } * \endcode */ class CBotToken : public CBotDoublyLinkedList { public: /** * \brief Default constructor */ CBotToken(); /** * \brief Copy constructor */ CBotToken(const CBotToken& pSrc); /** * \brief Constructor * * \param text The string this token represents * \param sep All separators that appeared after this token * \param start Beginning location in the source code of this token * \param end Ending location in the source code of this token */ CBotToken(const std::string& text, const std::string& sep = "", int start = 0, int end = 0); /** * \brief Destructor * * Be careful! This destroys the whole linked list of tokens * * Never call in the middle of the sequence - always on the first token in the list */ ~CBotToken(); /** * \brief Return the token type or the keyword id * \return A value from ::TokenType. For ::TokenTypKeyWord, returns the keyword ID instead. */ int GetType(); /** * \brief Return the token string * \return The string associated with this token */ std::string GetString(); /** * \brief Set the token string * \param name The new string to set */ void SetString(const std::string& name); /** * \brief Return the beginning location of this token in the original program string */ int GetStart(); /** * \brief Return the ending location of this token in the original program string */ int GetEnd(); /** * \brief SetPos Set the token position in the CBot program * \param start The start position of the token * \param end The end position of the token */ void SetPos(int start, int end); /** * \brief Get the keyword id * \return The keyword id, see ::TokenId */ long GetKeywordId(); /** * \brief Copy operator */ const CBotToken& operator=(const CBotToken& src); /** * \brief Transforms a CBot program from a string to a list of tokens * \param prog The program string * \return The first token in the linked list */ static std::unique_ptr CompileTokens(const std::string& prog); /** * \brief Define a new constant * \param name Name of the constant * \param val Value of the constant * \return true on success, false if already defined */ static bool DefineNum(const std::string& name, long val); /** * \brief Clear the list of defined constants * \see DefineNum() */ static void ClearDefineNum(); private: /** * \brief Find the next token in the string * * The string must not start with separators. The separator is part of the previous token. * * \param [in, out] program The program string, modified to point at the next token * \param first true if this is the first call (beginning of the program string) * \return A processed CBotToken */ static CBotToken* NextToken(const char*& program, bool first); private: //! The token type TokenType m_type = TokenTypVar; //! The id of the keyword long m_keywordId = -1; //! The token string std::string m_text = ""; //! The separator that appeared after this token std::string m_sep = ""; //! The strat position of the token in the CBotProgram int m_start = 0; //! The end position of the token in the CBotProgram int m_end = 0; //! Map of all defined constants (see DefineNum()) static std::map m_defineNum; /** * \brief Check if the word is a keyword * \param w The word to check * \return the keyword ID (::CBotTokenId), or -1 if this is not a keyword */ static int GetKeyWord(const std::string& w); /** * \brief Resolve a constant defined with DefineNum() * \param name Constant name * \param token Token that we are working on, will be filled with data about found constant * \return true if the constant was found, false otherwise */ static bool GetDefineNum(const std::string& name, CBotToken* token); }; /** * \brief Check if this token is of specified type * \param p The token to compare * \param type1 First token type to comapre to the token * \param type2 Second token type to comapre to the token * \return true if the type of the token matches one of the parameters */ extern bool IsOfType(CBotToken* &p, int type1, int type2 = -1); /** * \brief Check if this token is of specified type * \param p The token to compare * \param type1 The list of token types to comapre to the token, 0-terminated * \return true if the type of the tokens matched one of the parameters */ extern bool IsOfTypeList(CBotToken* &p, int type1, ...); /** * \brief Maps given ID to its string equivalent * \param id Token type identifier * \return String if found, empty string otherwise */ const std::string& LoadString(TokenId id);