В настоящее время я реализую компилятор для игрушечного языка «Micro» и создал несколько классов для работы с AST. Я использую инструмент парсера — Bison. Я сейчас пытаюсь сгенерировать сборку для циклов while и операторов if / else, но у меня возникла проблема с приведением объекта родительского класса ASTNode в качестве одного из его дочерних элементов, WhileNode.
В моем парсере я объявил свои типы возврата для всех этих узлов как родительский класс ASTNode.
%type <node> if_stmt stmt base_stmt loop_stmt read_stmt write_stmt control_stmt return_stmt assign_stmt else_part while_stmt func_decl
%union{
std::string* s;
std::list<std::string> * str_list;
ASTNode * node;
std::list<ASTNode*> * ast_list;
JumpType * jtype;
Conditional * condition;
}
В правиле while_stmt я инициализирую whileNode без содержащегося в нем stmt_list. Это позволяет точно хранить currentBlockID для создания меток, операторов ветвления и т. Д.
while_stmt : _WHILE _OPAREN cond _CPAREN decl
{
currentBlockID = scope_iterator;
SymbolTable* tmp = new SymbolTable("BLOCK " + std::to_string(scope_iterator++), ststack.top());
ststack.top()->children.push_back(tmp);
ststack.push(tmp);
$<node>$ = new WhileNode($3->left_expr, $3->right_expr, currentBlockID, $3->jtype, ASTNodeType::WHILE);
}
stmt_list _ENDWHILE
{
ststack.pop();
dynamic_cast<WhileNode *> $<node>6->copyStmtList(*7);
$$ = $<node>6;
}
;
Я определил WhileNode в середине правила, так что я могу перехватить currentBlockID до того, как этот blockID будет повторен в других конструкциях узла (узел if / else также будет увеличивать blockID.) Моя проблема связана с dynamic_cast в конце правила. Я пытался сделать это с помощью статического и динамического приведения, но у меня проблемы с обоими.
Вот ошибка, которую я сейчас получаю с динамическим приведением:
src/parser.yy: In function ‘int yyparse()’:
src/parser.yy:388:81: error: invalid type argument of unary ‘*’ (have ‘int’)
dynamic_cast<WhileNode *> $<node>6->copyStmtList(*7);
Я ссылался на этот вопрос для его реализации таким образом, но все еще были проблемы: Как я могу привести родительский класс в качестве дочернего класса.
Причина, по которой я использую dynamic_cast, заключается в том, что поскольку тип возвращаемого значения является ASTNode, у него нет дочернего метода copyStmtList (). Любая помощь в улучшении этого метода литья будет принята с благодарностью!
Ну, я дурак. Я не осознавал, что случайно пропустил ‘$’ из ‘* $ 7’, и в этом случае попытка что-либо сделать с * 7 — это просто разыменование типа int (что явно недопустимо). Я извиняюсь за ошибку.
Других решений пока нет …