Как визуализировать абстрактное синтаксическое дерево графически?

Я написал простой компилятор на C ++ и хочу визуализировать абстрактное синтаксическое дерево, которое оно создает. В настоящее время я выкидываю AST в супер длинную строку, похожую на что-то ниже:


Program(decls=[ConstDecl(type=BasicTypeKind::Int, value=Num(n=1, loc=Location(1, 21)), name=positive, loc=Location(1, 10)), ConstDecl(type=BasicTypeKind::Int, value=Num(n=-1, loc=Location(2, 21)), name=negative, loc=Location(2, 10)), ConstDecl(type=BasicTypeKind::Int, value=Num(n=100, loc=Location(3, 26)), name=max_heap_size, loc=Location(3, 10)), ConstDecl(type=BasicTypeKind::Character, value=Char(c=99, loc=Location(4, 23)), name=...

Как видите, этот дамп не очень удобен для человека с точки зрения визуализации. Нельзя естественно связать понятие дерево до такой длинной строки. Я попробовал подход, чтобы красиво распечатать AST и нашел astpretty, который для Python. Он нацелен на отладку, но что, если я хочу иллюстрацию AST? Графический формат, безусловно, подходит лучше.

На самом деле у меня есть картина о том, какой выход я с нетерпением жду. Graphviz делает большую работу в этой области и различных графиков инструмент документа C ++ Doxygen концептуально очень близки к моей цели.

Собирая их вместе, я хочу, чтобы способ превращать AST в памяти как объекты C ++ в приличный графический вывод (статический в порядке). Есть хорошая отправная точка?

Редактировать: как сказано в комментариях, сбрасывает мой AST в формате Graphviz признает это хорошая отправная точка. Я постараюсь сделать это так, пока не возникнут новые и более конкретные проблемы. Спасибо, парни.

0

Решение

Я нашел решение, которое было бы быстрым и приемлемым. LLVM-8 включает в себя возможность визуализации графика потока управления (CFG) путем создания из него файла точечного формата. В основном это работает для более общих структур графов, если вы специализируете llvm::GraphTraits а также llvm::DOTGraphTraits шаблоны (с небольшой работой вокруг) и llvm::WriteGraph() будет работать на вас. Вот результат без особой подстройки:

введите описание изображения здесь

учитывая C-подобный фрагмент:

const int IntConstant = 1;
int Array[2];

void main() {
Printf("hello");
}

Этот язык является упрощением языка Си и нечувствителен к регистру. Printf() представлен Write Заявление в качестве узла на изображении. ConstDecl средства постоянная декларация. VarDecl средства объявление переменной а также FuncDef средства определение функции. Другие вещи довольно просты.

Прежде чем объяснить магию, я хотел бы указать вам на эти документы, которые действительно помогают использовать задействованный APT llvm.

  • GraphTraits знать подпись, которую должен иметь ваш код.
  • WriteGraph знать что WriteGraph требует вашего кода.
  • CFGPrinter знать, как специализировать свой GraphTraits
  • DOTGraphTraits знать, как сделать вашу иллюстрацию значимой, давая метки и описания узлам.
  • iterator_facade_base уметь безболезненно писать рабочие итераторы.

Теперь с этими базами знаний, вам просто нужно собрать их вместе. На самом деле, выполните следующие действия:

  1. думать о том, как перебрать каждый узел в AST и специализировать nodes_iterator реализация.
  2. думать о том, как перебрать все дочерние узлы данного узла и специализировать ChildIteratorType реализация.
  3. подумайте, как извлечь полезную информацию из ваших узлов и специализировать getNodeLabel() а также getNodeDescription() вашей DOTGraphTraits,
  4. обратите внимание на мой: NodeRef тип GraphTraits должен быть указателем! знание этого заранее может сэкономить вам день. Это верно для последней версии. Возможно, в будущем они снимают ограничения.

Моя текущая реализация включает в себя только имя класса узла в качестве его метки и понятную строку в качестве его описания без какой-либо тонкой настройки. Если вы хотите больше эффектов, например, цвета, формы и т. Д., Вы можете сделать это в своем DOTGraphTraits,

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]