247 lines
6.8 KiB
C++
247 lines
6.8 KiB
C++
/*
|
|
* 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 <vector>
|
|
#include <string>
|
|
#include <map>
|
|
#include <memory>
|
|
|
|
/**
|
|
* \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<CBotToken> tokens = CBotToken::CompileTokens(program);
|
|
* CBotToken* token = tokens.get();
|
|
* while(token != nullptr)
|
|
* {
|
|
* printf("%s\n", token->GetString());
|
|
*
|
|
* token = token->GetNext();
|
|
* }
|
|
* \endcode
|
|
*/
|
|
|
|
class CBotToken : public CBotDoublyLinkedList<CBotToken>
|
|
{
|
|
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<CBotToken> 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<std::string, long> 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);
|