Полиморфное абстрактное синтаксическое дерево (парсер рекурсивного спуска): невозможно?

Я начал писать анализатор полиморфного рекурсивного спуска на C ++. Однако у меня есть проблема. Классы настроены так:

class Node {
public:
std::vector<Node*> children;
};

class NodeBinary : public Node {
public:
Node* left;
Node* right;
};

class NodeUnary : public Node {
public:
Node* operand;
};

class NodeVar : public Node {
public:
std::string string;
NodeVar(std::string str) : string(str) {};
};

class NodeNumber : public Node {
public:
signed long number;
NodeNumber(signed long n) : number(n) {};
};

// etc.

А потом классы вроде NodeDeclaration, NodeCall, NodeNot, NodeAssignment, NodePlus, NodeMinus, NodeIf и т.д. унаследует либо от Node или что-то менее общее, как NodeBinary или же NodeUnary,

Однако некоторые из них принимают более конкретные операнды. NodeAssignment всегда принимает переменную и число / выражение. Поэтому мне придется переопределить Node * влево, NodeVar * влево и NodeExpr * вправо. Проблема приходит с такими вещами, как NodePlus, Слева может быть NodeVar или NodeExpr! И у корневого узла есть похожая проблема: при синтаксическом анализе на верхнем уровне, чтобы добавить дочерние узлы в корневой каталог, как можно определить, является ли дочерний узел NodeExpr, NodePlus, NodeIf так далее…?

Я мог бы иметь все узлы с перечислимым «типом», который говорит, что это за тип, но тогда какой смысл иметь красивое полиморфное дерево наследования?

Как эта проблема обычно решается ??

0

Решение

Если вы используете наследование классов для своих узлов AST, вам необходимо создать соответствующую иерархию наследования, как и в любом объектно-ориентированном проектировании.

Так, например, NodeAssignment (что, вероятно, является специализацией NodeStatement) должен содержать NodeLValue (из которых NodeVariable это специализация) и NodeValue, Как обычно, LValues ​​(то есть вещи, которые вы можете назначить) являются подмножеством значений, поэтому NodeLValue будет специализация NodeValue, И так далее. Ваш бинарный операторный узел будет содержать left а также right члены, оба из которых являются NodeValue базовые объекты (я бы ожидал NodeValue быть чисто виртуальным, с большим количеством конкретных специализаций.)

Если вы настаиваете на использовании парсера рекурсивного спуска, каждая функция синтаксического анализа должна возвращать соответствующий подкласс Node, так что функция, которая анализирует левую часть присваивания, логически возвращает NodeLValue*готовы вставить в NodeAssignment конструктор. (Честно говоря, я бы отказался от слова Node во всех этих именах классов. Поместите их все в пространство имен node:: и сэкономить немного печатать.)

0

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

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

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