elna/include/elna/boot/symbol.h

129 lines
3.0 KiB
C++

// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#pragma once
#include <cstdint>
#include <unordered_map>
#include <string>
#include <memory>
namespace elna
{
namespace boot
{
/**
* Generic language entity information.
*/
template<typename T>
class info
{
public:
T payload;
info(T payload)
: payload(payload)
{
}
};
template<typename T>
std::shared_ptr<info<T>> make_info(T payload)
{
return std::make_shared<info<T>>(info(payload));
}
/**
* Symbol table.
*/
template<typename T>
class symbol_table
{
public:
using symbol_ptr = std::shared_ptr<info<T>>;
using iterator = typename std::unordered_map<std::string, symbol_ptr>::iterator;
using const_iterator = typename std::unordered_map<std::string, symbol_ptr>::const_iterator;
private:
std::unordered_map<std::string, symbol_ptr> entries;
std::shared_ptr<symbol_table> outer_scope;
public:
/**
* Constructs a new symbol with an optional outer scope.
*
* \param scope Outer scope.
*/
explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr)
: outer_scope(scope)
{
}
iterator begin()
{
return entries.begin();
}
iterator end()
{
return entries.end();
}
const_iterator cbegin() const
{
return entries.cbegin();
}
const_iterator cend() const
{
return entries.cend();
}
/**
* Looks for symbol in the table by name. Returns nullptr if the symbol
* can not be found.
*
* \param name Symbol name.
* \return Symbol from the table if found.
*/
symbol_ptr lookup(const std::string& name)
{
auto entry = entries.find(name);
if (entry != entries.cend())
{
return entry->second;
}
if (this->outer_scope != nullptr)
{
return this->outer_scope->lookup(name);
}
return nullptr;
}
/**
* Registers new symbol.
*
* \param name Symbol name.
* \param entry Symbol information.
*
* \return Whether the insertion took place.
*/
bool enter(const std::string& name, symbol_ptr entry)
{
return entries.insert({ name, entry }).second;
}
/**
* Returns the outer scope or nullptr if the this is the global scope.
*
* \return Outer scope.
*/
std::shared_ptr<symbol_table> scope()
{
return this->outer_scope;
}
};
}
}