Некоторое время я пытался реализовать AST на С++ для хранения данных, полученных из языка ML, вот инструкция, которую мой AST может записать:
var foo = 8;
Лексер изолирует токены, а синтаксический анализатор делает вывод, что это объявление переменной, поэтому он изолирует все:
foo = 8
Из этого было легко построить временный AST:
=
/ \
foo 8
Но я все еще не могу справиться с дочерними узлами:
foo = 2 + 4
Or
foo : integer = 2 + 4
Итак, кто должен дать это:
=
/ \
/ \
: +
/ \ / \
/ \ 2 4
foo integer
Вот моя попытка реализации:
*.hpp
enum NodeTypes { /* ... */ };
struct Node {
token_t NodeValue;
NodeTypes NodeType;
Node *LeftChild = NULL;
Node *RightChild = NULL;
Node(token_t value, NodeTypes type);
void InsertLeft(token_t NodeValue, NodeTypes NodeType = NOTHING);
void InsertRight(token_t NodeValue, NodeTypes NodeType = NOTHING);
void BrowseUp();
};
*.cpp
Node(token_t value, NodeTypes type) {
NodeValue = value;
NodeType = type;
}
void InsertLeft(token_t value, NodeTypes type) {
if (LeftChild == NULL)
LeftChild = new Node(value, type);
else {
Node NewNode = Node(value, type);
NewNode.LeftChild = LeftChild;
LeftChild = &NewNode;
}
}
void InsertRight(token_t value, NodeTypes type) {
if (RightChild == NULL)
RightChild = new Node(value, type);
else {
Node NewNode = Node(value, type);
NewNode.RightChild = RightChild;
RightChild = &NewNode;
}
}
void BrowseUp() {
std::cout << NodeValue.value << " ";
if (LeftChild) LeftChild->BrowseUp();
if (RightChild) RightChild->BrowseUp();
}
Используй это:
Node main = Node(NodePosition, NodeType);
SetMainAst(main, expr);
main.BrowseUp();
SetMainAst:
void SetMainAst(Node &node, Expr expr, NodeTypes type = NodeTypes::NOTHING) {
std::array<Expr, 3> exp = CutExpr(expr, GetNodePosition(expr));
Expr left = exp[0], right = exp[2];
token_t value = exp[1][0];
if (type == NOTHING) node.NodeValue = value;
if (!ContainNodes(left)) node.InsertLeft(left[0]);
else SetMainAst(node, left, DetermineFirstNode(expr));
if (!ContainNodes(right)) node.InsertRight(right[0]);
else SetMainAst(node, right, DetermineFirstNode(expr));
}
CutExpr() позволяет разрезать выражение на 3 части:
- lзначение;
- узел;
- значение.
Я помог себе с этим (это на питоне, но я переписал на С++).
С одним выражением узла это творит чудеса. Но при наличии более одного узла он больше не работает: BrowseUp() останавливает программу после отображения основного узла (т.е. знака равенства в данном случае).
Я действительно не понимаю, но я хорошо следовал руководству и думаю, что хорошо расшифровал на С++... Может быть, это проблема указателя/ссылки?
Буду очень признателен, если вы поможете мне решить эту проблему (которая беспокоит меня уже 3 дня).
LeftChild = &NewNode;
-- указатель на локальную переменную, которая переживает локальную область видимости - person Yakk - Adam Nevraumont   schedule 15.08.2018delete
на каждом узле, вы понимаете, что некоторые из ваших узлов не были созданы с помощьюnew
, поэтому вы бы застряли. - person PaulMcKenzie   schedule 15.08.2018