You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
6.2 KiB

/*
* FCML - Free Code Manipulation Library.
* Copyright (C) 2010-2019 Slawomir Wojtasiak
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @file fcml_symbols.hpp
* C++ API for symbols handling. Currently used only by parsers.
*
* @copyright Copyright (C) 2010-2015 Slawomir Wojtasiak. All rights reserved.
* This project is released under the GNU Lesser General Public License.
*/
#ifndef FCML_SYMBOLS_HPP_
#define FCML_SYMBOLS_HPP_
#include <new>
#include "fcml_common.hpp"
#include "fcml_symbols.h"
namespace fcml {
/**
* Represents one named symbol with associated value.
* @since 1.1.0
*/
class Symbol {
public:
/**
* Creates an empty symbol.
* @since 1.1.0
*/
Symbol() :
_value(0) {
}
/**
* Creates a symbol instance for the given name and value.
*
* @param name The symbol name.
* @param value The symbol value.
* @since 1.1.0
*/
Symbol(const fcml_cstring &name, fcml_int64_t value) :
_name(name), _value(value) {
}
/**
* Gets symbol value.
* @since 1.1.0
*/
operator fcml_uint64_t() const {
return _value;
}
/**
* Gets symbol value.
* @since 1.1.0
*/
operator fcml_int64_t() const {
return static_cast<fcml_int64_t>(_value);
}
/**
* Gets true if symbol is empty.
*
* @return True if symbol is empty.
* @since 1.1.0
*/
bool isEmpty() const {
return _name.empty();
}
/**
* Gets the symbol name.
*
* @return The symbol name.
* @since 1.1.0
*/
const fcml_cstring& getName() const {
return _name;
}
/**
* Gets the symbol value.
*
* @return The symbol value.
* @since 1.1.0
*/
fcml_uint64_t getValue() const {
return _value;
}
/**
* Sets a new symbol name.
*
* @param name The symbol name.
* @since 1.1.0
*/
void setName(const fcml_cstring &name) {
_name = name;
}
/**
* Sets a new symbol value.
*
* @param value The symbol value.
* @since 1.1.0
*/
void setValue(fcml_uint64_t value) {
_value = value;
}
private:
// Symbol name.
fcml_cstring _name;
// Symbol value.
fcml_uint64_t _value;
};
/* Due to the performance purposes and the way symbol table is managed
* internally, it has to be wrapped directly without doing any conversions
* when needed.
* @since 1.1.0
*/
class SymbolTable: public NonCopyable {
public:
/**
* Creates an empty symbol table.
* @throw InitException The symbol table can't be allocated.
* @since 1.1.0
*/
SymbolTable() :
_symbolTable(NULL) {
_symbolTable = ::fcml_fn_symbol_table_alloc();
if (!_symbolTable) {
throw InitException(
FCML_TEXT(
"Symbol table can not be initialized correctly."));
}
}
/**
* Destructor.
* @since 1.1.0
*/
virtual ~SymbolTable() {
if (_symbolTable) {
::fcml_fn_symbol_table_free(_symbolTable);
_symbolTable = NULL;
}
}
protected:
friend class SymbolTableAware;
/**
* Gets native FCML symbol table.
* @return The native symbol table.
* @since 1.1.0
*/
fcml_st_symbol_table& getSymbolTable() {
return _symbolTable;
}
public:
/**
* Adds a new symbol to the table.
*
* @param symbolName The symbol name.
* @param value The symbol value.
* @since 1.1.0
*/
void add(const fcml_cstring &symbolName, fcml_int64_t value) {
if (::fcml_fn_symbol_add_raw(_symbolTable, symbolName.c_str(), value)
== FCML_CEH_GEC_OUT_OF_MEMORY) {
throw std::bad_alloc();
}
}
/**
* Removes symbol from the table.
*
* @param symbolName The symbol name.
* @since 1.1.0
*/
void remove(const fcml_cstring &symbolName) {
const fcml_string key = symbolName.c_str();
::fcml_fn_symbol_remove(_symbolTable, key);
}
/**
* Gets true if there is a symbol for the given name in the table.
*
* @param symbolName The symbol name.
* @return true If symbol of the name exists in the table.
* @since 1.1.0
*/
bool contains(const fcml_cstring &symbolName) const {
return ::fcml_fn_symbol_get(_symbolTable, symbolName.c_str()) != NULL;
}
/**
* Gets the symbol of the given name. Checks Symbol.isEmpty method of the
* returned symbol to check if there is such a symbol.
*
* @param symbolName The symbol name.
* @return The found symbol.
* @since 1.1.0
*/
Symbol get(const fcml_cstring &symbolName) const {
Symbol symbol;
fcml_st_symbol *found_symbol = ::fcml_fn_symbol_get(_symbolTable,
symbolName.c_str());
if (found_symbol) {
symbol.setName(found_symbol->symbol);
symbol.setValue(found_symbol->value);
}
return symbol;
}
private:
/** The native FCML symbol table. */
fcml_st_symbol_table _symbolTable;
};
/**
* Derive from this class if you really need access to the native symbol table.
* @since 1.1.0
*/
class SymbolTableAware {
public:
/**
* Extracts the native symbol table for the given symbol table wrapper.
* @param symbolTable The symbol table wrapper.
* @since 1.1.0
*/
fcml_st_symbol_table& extractSymbolTable(SymbolTable &symbolTable) {
return symbolTable.getSymbolTable();
}
};
}
#endif /* FCML_SYMBOLS_HPP_ */