我目前正在为玩具语言“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 规则中,我在没有包含 stmt_list 的情况下初始化 WhileNode。这样我就可以准确地存储 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,这样我就可以在其他节点构造中迭代此 blockID 之前捕获 currentBlockID(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);
我已经引用了这个问题以这种方式实现它,但仍然遇到问题:How do I cast a parent class as the child class。
我使用 dynamic_cast 的原因是因为返回类型是 ASTNode,它没有子方法 copyStmtList()。任何有关改进这种铸造方法的帮助将不胜感激!