Я написал синтаксический анализатор LR(1), который может успешно анализировать строки на языке моей грамматики в конкретное синтаксическое дерево, но сейчас я пытаюсь построить абстрактное синтаксическое дерево.
Я использую схему наследования для своих узлов AST:
struct ASTNode {
virtual Type typeCheck() = 0;
}
struct IDNode : public ASTNode {
string name;
...
}
struct INTNode : public ASTNode {
int value;
...
}
struct BOPNode : public ASTNode {
ASTNode *pLeft;
ASTNode *pRight;
...
}
struct Add_BOPNode : public BOPNode {
...
}
struct ParamNode : public ASTNode {
string name;
ASTNode *pTypeSpecifier;
...
}
struct ParamListNode : public ASTNode {
vector<ParamNode*> params;
...
}
struct FuncDec : public ASTNode {
string functionName;
ASTNode *pFunctionBody;
ASTNode *pReturnType;
ASTNode *pParams;
...
}
Когда я выполняю сокращение в парсере LR(1), я генерирую новый узел в зависимости от правила, которое использовалось для сокращения. Это довольно просто для большинства узлов, но я не уверен в правильном способе реализации узла, содержащего список других узлов.
Используя ParamListNode выше в качестве примера:
struct stack_item {
int state;
int token;
string data;
ASTNode *node;
};
/// rule = the number of the rule being reduced on
/// rhs = the items on the right-hand side of the rule
ASTNode* makeNode(int rule, vector<stack_item> rhs) {
switch(rule) {
/// <expr> ::= <expr> '+' <term>
case 1: return new Add_BOPNode(rhs[0].node, rhs[2].node);
/// <param> ::= IDENT(data) ':' <type>
case 2: return new ParamNode(rhs[0].data, rhs[2].node);
/// <param_list> ::= <param>
case 3: return new ParamList(rhs[0].node);
/// <param_list> ::= <param_list> ',' <param>
case 4: {
auto list = dynamic_cast<ParamListNode*>(rhs[0].node);
list->params.push_back(rhs[2].node);
return list;
}
...
}
}
Поскольку для создания узла требуется возврат подкласса ASTNode, я должен создать подкласс, который заключает в себе вектор‹> с каждым подузлом. Однако, поскольку не каждый узел должен быть структурой списка, мне нужно выполнить dynamic_cast‹> к подклассу, прежде чем я смогу получить доступ к внутреннему списку.
Я чувствую, что должен быть более чистый способ обработки списка подузлов без необходимости полагаться на dynamic_cast‹>.
Еще вопрос по узлу FuncDec. У него есть pParams, который должен быть ParamList (или vector‹Param*> напрямую), но для этого мне пришлось бы dynamic_cast‹> входящий ASTNode в узел ParamList или Param. Опять же, я чувствую, что должен быть способ не использовать dynamic_cast‹>, но я не могу его придумать.
Кроме того, если у вас есть какие-либо другие предложения о том, как я могу лучше структурировать или реализовать что-либо, я буду очень признателен :)
stack_item
? - person Simon Kraemer   schedule 19.02.2016stack_item
? Не проще ли построить узлы напрямую, используя конкретные типы? - person Simon Kraemer   schedule 19.02.2016node
в stack_item. Кроме того, некоторые символы в правой части правила являются терминалами со связанными с ними данными, такими как IDENT (данные), поэтому мне также нужно было иметь возможность передавать эти данные на ASTNode, которым они нужны. - person Sarathi   schedule 19.02.2016