utree
представляет собой динамически типизированную иерархическую структуру данных, которая может представлять абстрактные синтаксические деревья. Он хорошо интегрирован сДухом.QiиДухом. карма.utree
можно передать как атрибут почти любой грамматики.utree
’s type system реализована с помощью дискриминационного союза и каламбура типа.
utree
имеет минимальный отпечаток памяти. Размер структуры данных составляет 16 байт на 32-битной платформе и 32 байта на 64-битной платформе4*размерпустота*
. Будучи контейнером, он может представлять собой древесные структуры.
Каждый экземпляр структуры данныхutree
может одновременно хранить один из следующих типов данных:
struct utree_type
{
enum info
{
invalid_type,
nil_type,
list_type,
range_type,
reference_type,
any_type,
function_type,
bool_type,
int_type,
double_type,
string_type,
string_range_type,
symbol_type,
binary_type
};
typedef boost::uint_t<sizeof(info)*8>::exact exact_integral_type;
typedef boost::uint_t<sizeof(info)*8>::fast fast_integral_type;
};
Струна UTF-8, символ UTF-8 и двоичные типы данных внутренне хранятся либо непосредственно как данные узла (применяется оптимизация малой строки), либо они выделяются из кучи, сохраняя указатель на выделенные данные вутре
. Максимально возможная длина данных, которые будут храниться в данных узла, зависит от платформы, для которой скомпилированоутри
. Это 14 байт для 32-битной платформы и 30 байт для 64-битной платформы.
Структура данныхутри
очень универсальна и может использоваться в качестве атрибута для всех возможныхSpirit.Qiпарсеров иДух. Кармагенераторы. По этой причине он раскрывает набор типдефов, что делает его совместимым с контейнерами STL:
typedef utree value_type;
typedef utree& reference;
typedef utree const& const_reference;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef detail::list::node_iterator<utree> iterator;
typedef detail::list::node_iterator<utree const> const_iterator;
Тип данныхutree
раскрывает функциональный интерфейс двунаправленного STL-контейнера. Итераторы, возвращаемые из, начинают()
и т.д., соответствуют стандартным требованиям двунаправленного итератора.
template <class T>
void push_back(T const&);
template <class T>
void push_front(T const&);
template <class T>
iterator insert(iterator, T const&);
template <class T>
void insert(iterator, std::size_t, T const&);
template <class Iterator>
void insert(iterator, Iterator, Iterator);
void pop_front();
void pop_back();
iterator erase(iterator);
iterator erase(iterator, iterator);
reference front();
const_reference front() const;
iterator begin();
const_iterator begin() const;
ref_iterator ref_begin();
reference back();
const_reference back() const;
iterator end();
const_iterator end() const;
ref_iterator ref_end();
Обнаруженный интерфейс контейнера позволяет использоватьутри
со всемиSpirit.Qiпарсер иДух. КармаГенераторные компоненты, которые совместимы с типом атрибута контейнера STL.
Autree
может быть построен или инициализирован из широкого спектра типов данных, что позволяет создаватьutree
экземпляры для каждого возможного типа узла (см. описаниеutree_type::информация
выше). По этой причине он предоставляет конструктор и оператор назначения для каждого из разрешенных типов узлов, как показано ниже. Все конструкторы неявны по назначению, что позволяет использовать экземпляр утри в качестве атрибута практически любому ци-парсеру.
utree(invalid_type = invalid_type());
utree(nil_type);
reference operator=(nil_type);
explicit utree(bool);
reference operator=(bool);
utree(unsigned int);
utree(int);
reference operator=(unsigned int);
reference operator=(int);
utree(double);
reference operator=(double);
utree(char);
utree(char const*);
utree(char const*, std::size_t);
utree(std::string const&);
reference operator=(char);
reference operator=(char const*);
reference operator=(std::string const&);
utree(utf8_string_range_type const&, shallow_tag);
utree(boost::reference_wrapper<utree>);
reference operator=(boost::reference_wrapper<utree>);
utree(any_ptr const&);
reference operator=(any_ptr const&);
template <class Iterator>
utree(boost::iterator_range<Iterator>);
template <class Iterator>
reference operator=(boost::iterator_range<Iterator>);
utree(function_base const&);
reference operator=(function_base const&);
utree(function_base*);
reference operator=(function_base*);
template <class Base, utree_type::info type_>
utree(basic_string<Base, type_> const&);
template <class Base, utree_type::info type_>
reference operator=(basic_string<Base, type_> const&);
Тип данныхutree
предоставляет функциональный интерфейс, совместимый сBoost.Variant. Его природа заключается в том, чтобы хранить различные типы данных, по одному в каждый момент времени, что делает его функционально очень похожим наBoost.Variant.
utree_type::info which() const;
template <class T>
T get() const;
Обнаруженный вариантный интерфейс делаетутри
пригодными для использования со всемиSpirit.Qiпарсер иSpirit. Компоненты генератора кармы, совместимые с типом атрибута Boost.Variant.
utree
типы строк, описанные ниже, используются только APIutree
. Они не используются для хранения информации вутре
. Они предназначены для обозначения различных внутреннихутре
типов узлов. Например, созданиеutree
из двоичного типа данных создастдвоичный_type
узел utree (см. выше).
Тип двоичных данных может быть представлен либо дословно как последовательность байтов, либо как пара итераторов в некоторую другую сохраненную двоичную последовательность данных. Используйте этот тип строки для доступа/созданиядвоичного_типа
утре
.
typedef basic_string<
boost::iterator_range<char const*>, utree_type::binary_type
> binary_range_type;
typedef basic_string<
std::string, utree_type::binary_type
> binary_string_type;
Струна UTF-8 может быть представлена либо дословно как последовательность символов, либо как пара итераторов в некоторую другую сохраненную двоичную последовательность данных. Используйте этот тип строки для доступа/созданиястроки_типа
утри
.
typedef basic_string<
boost::iterator_range<char const*>, utree_type::string_type
> utf8_string_range_type;
typedef basic_string<
std::string, utree_type::string_type
> utf8_string_type;
Символ UTF-8 может быть представлен либо дословно как последовательность символов, либо как пара итераторов в некоторую другую сохраненную двоичную последовательность данных. Используйте этот тип строки для доступа/созданиясимвола_типа
утре
.
typedef basic_string<
boost::iterator_range<char const*>, utree_type::symbol_type
> utf8_symbol_range_type;
typedef basic_string<
std::string, utree_type::symbol_type
> utf8_symbol_type;
Класс шаблонов хранимых_функций может хранить унарные функциональные объекты с подписью utree (scope const&) как узел утри.
struct function_base
{
virtual ~function_base() {}
virtual utree operator()(utree const& env) const = 0;
virtual utree operator()(utree& env) const = 0;
virtual function_base* clone() const = 0;
};
template <typename F>
struct stored_function : function_base
{
F f;
stored_function(F f = F());
virtual ~stored_function();
virtual utree operator()(utree const& env) const;
virtual utree operator()(utree& env) const;
virtual function_base* clone() const;
};
template <typename F>
struct referenced_function : function_base
{
F& f;
referenced_function(F& f);
virtual ~referenced_function();
virtual utree operator()(utree const& env) const;
virtual utree operator()(utree& env) const;
virtual function_base* clone() const;
};
Все исключения, внесенные utree, являются производными от utree_исключения.
struct utree_exception : std::exception {};
bad_type_ Exception
выбрасывается всякий раз, когда кто-то вызывает функцию члена, которая применяется только к определенному сохраненному типу utree_type, но это предварительное условие нарушается, поскольку экземплярutree
содержит какой-то другой тип.
struct bad_type_exception ;
пустое_исключение
выбрасывается всякий раз, когда предварительное условие метода списка или диапазона utree нарушается из-за того, что список или диапазон пусты.
struct empty_exception ;
Наш первый пример показывает, как использоватьутри
для написания парсера длясимволических выражений. В то время какutree
способен представлять практически любую AST,utree
дизайн основан на простой, но мощной природе символических выражений. В этом примере представлен ряд основных и промежуточныхутри
методов развития: с использованиемSpirit.QiиSpirit. Кармаинтеграция, отслеживание местоположения исходного кода и использование поддержки UTF8.
Источник для этого примера можно найти здесь:../../пример/поддержка/utree.
namespace sexpr
{
template <typename Iterator, typename ErrorHandler = error_handler<Iterator> >
struct parser : qi::grammar<Iterator, utree(), whitespace<Iterator> >
{
qi::rule<Iterator, utree(), whitespace<Iterator> >
start, element, list;
qi::rule<Iterator, utree()>
atom;
qi::rule<Iterator, int()>
integer;
qi::rule<Iterator, utf8_symbol_type()>
symbol;
qi::rule<Iterator, utree::nil_type()>
nil_;
qi::rule<Iterator, binary_string_type()>
binary;
utf8::parser<Iterator>
string;
px::function<ErrorHandler> const
error;
tagger<Iterator, save_line_pos>
pos;
parser(std::string const& source_file = "<string>"):
parser::base_type(start), error(ErrorHandler(source_file))
{
using standard::char_;
using qi::unused_type;
using qi::lexeme;
using qi::hex;
using qi::oct;
using qi::no_case;
using qi::real_parser;
using qi::strict_real_policies;
using qi::uint_parser;
using qi::bool_parser;
using qi::on_error;
using qi::fail;
using qi::int_;
using qi::lit;
using qi::_val;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
real_parser<double, strict_real_policies<double> > strict_double;
uint_parser<unsigned char, 16, 2, 2> hex2;
bool_parser<bool, sexpr::bool_input_policies> boolean;
start = element.alias();
element = atom | list;
list = pos(_val, '(') > *element > ')';
atom = nil_
| strict_double
| integer
| boolean
| string
| symbol
| binary;
nil_ = qi::attr_cast(lit("nil"));
integer = lexeme[ no_case["#x"] > hex]
| lexeme[ no_case["#o"] >> oct]
| lexeme[-no_case["#d"] >> int_];
std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0';
symbol = lexeme[+(~char_(exclude))];
binary = lexeme['#' > *hex2 > '#'];
start.name("sexpr");
element.name("element");
list.name("list");
atom.name("atom");
nil_.name("nil");
integer.name("integer");
symbol.name("symbol");
binary.name("binary");
on_error<fail>(start, error(_1, _2, _3, _4));
}
};
}