Я использую Ци и Карму для обработки некоторых небольших языков.Большинство грамматик довольно маленькие (20-40 правил).Я был в состоянии использовать autorules почти исключительно, поэтому мои деревья разбора полностью состоят из вариантов, структур и std :: vectors.
Эта установка прекрасно работает для общего случая:
1) анализирует что-то (Qi),
2) делает незначительные манипуляции с деревом анализа (посетителем) и
3) выводит что-то(Карма).
Однако меня беспокоит, что произойдет, если я захочу внести сложные структурные изменения в синтаксическое дерево, например, перемещать большие поддеревья.Рассмотрим следующий игрушечный пример:
Грамматика для логических выражений в стиле s-expr, использующая авторские правила ...
// Inside grammar class; rule names match struct names...
pexpr %= pand | por | var | bconst;
pand %= lit("(and ") >> (pexpr % lit(" ")) >> ")";
por %= lit("(or ") >> (pexpr % lit(" ")) >> ")";
pnot %= lit("(not ") >> pexpr >> ")";
..., которая приводит к представлению дерева разбора, которое выглядит следующим образом...
struct var {
std::string name;
};
struct bconst {
bool val;
};
struct pand;
struct por;
struct pnot;
typedef boost::variant<bconst,
var,
boost::recursive_wrapper<pand>,
boost::recursive_wrapper<por>,
boost::recursive_wrapper<pnot> > pexpr;
struct pand {
std::vector<pexpr> operands;
};
struct por {
std::vector<pexpr> operands;
};
struct pnot {
pexpr victim;
};
// Many Fusion Macros here
Предположим, у меня есть дерево разбора, которое выглядит примерно так:
pand
/ ... \
por por
/ \ / \
var var var var
(Многоточие означает «еще много детей одинаковой формы для pand
».)
Теперь предположим, что я хочу отменить каждый из por
узлов, так что конечный результат будет:
pand
/ ... \
pnot pnot
| |
por por
/ \ / \
var var var var
Прямой подход будет для каждого por
поддерева:
- создать pnot
узел
(копии por
в разработке);
- переназначить соответствующий векторный слот в узле pand
(копии pnot
узла и егоpor
поддерево).
В качестве альтернативы я мог бы создать отдельный вектор, а затем заменить (поменять) вектор pand
оптом, исключив второй раунд копирования.
Все это кажется громоздким по сравнению с указателемпредставление на основе дерева, которое позволит вставлять узлы pnot
без какого-либо копирования существующих узлов.Мой вопрос:
Есть ли способ избежать манипуляций с копирующим деревом с помощью авторул-совместимых структур данных?Должен ли я прикусить пулю и просто использовать неавторичные правила для создания AST на основе указателей (например, http://boost -spirit.com / home / 2010/03/11 / s-выражения и варианты) * )