129 lines
3.0 KiB
C++
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;
|
|
}
|
|
};
|
|
}
|
|
}
|