Печать синтаксического дерева как динамического списка на языке c

Я написал код на C для реализации таблицы разбора LR(1), однако сейчас я сталкиваюсь с проблемой печати дерева разбора. Как мы это делаем в C? Дерево может иметь переменные дочерние элементы, и, поскольку алгоритм синтаксического анализа является восходящим, я не уверен, с чего начать. Я хочу, чтобы это выглядело как результат pstree команда или что-то в этом роде.

Благодарю вас

1 ответ

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

Я собирался вставить доказательство того, что не получается нарисовать дерево синтаксического анализа, пока вы выполняете синтаксический анализ слева направо, но, к моему удивлению, я убедил себя, что это возможно, если вы немного ослабите правила: Вы должны быть в состоянии перемещать курсор вверх и вниз, влево и вправо, но вы можете делать это без всякой надпечатки. Чтобы сделать это, вы должны нарисовать дерево с листьями (терминалами) либо на левом поле, либо наверху, а затем вы можете нарисовать сокращения, рисуя линии от каждого дочернего элемента и помня, что такое "точка соединения" результирующий узел есть. Я не знаю, подходит ли это упражнение по программированию для кого-то, кто только начинает разбирать, но это возможно, даже с консольным приложением.

Вот пример графика "обратного pstree":

(41*x) + (27/y) - sin(2*pi*z);

(───────────────────────┐
41─factor─term┐         │
*─────────────┤         │
x─factor──────┴term─expr┤
)───────────────────────┴factor─term─expr┐
+────────────────────────────────────────┤
(───────────────────────┐                │
27─factor─term┐         │                │
/─────────────┤         │                │
y─factor──────┴term─expr┤                │
)───────────────────────┴factor─term─────┴expr┐
-─────────────────────────────────────────────┤
sin─────────────────────────┐                 │
(───────────────────────────┤                 │
2─factor─term┐              │                 │
*────────────┤              │                 │
pi─factor────┴term┐         │                 │
*─────────────────┤         │                 │
z─factor──────────┴term─expr┤                 │
)───────────────────────────┴factor─term──────┴expr

Алгоритм, используемый для получения, который сохраняет ширину и высоту каждого элемента стека; Терминалы начинаются с высоты 1 и ширины самого терминала. В каждом правиле сокращения:

  • курсор перемещается вправо, пока не окажется справа от каждого дочернего элемента;

  • курсор перемещается вверх первого дна

  • для каждого дочернего элемента горизонтальная линия рисуется из его нижнего правого угла в столбец, в котором находится курсор, а затем вертикальная линия отображается до тех пор, пока не будет достигнута строка следующего дочернего элемента. На последнем дочернем элементе печатается нетерминальное имя сокращения, а высота и ширина результирующего нетерминала записываются.

Другие вопросы по тегам