#include "visitor.h" #include #include #include "MXParser.h" #include "MXParserVisitor.h" #include "ast/ast.h" #include "ast/scope.hpp" #include "tools.h" std::any Visitor::visitMxprog(MXParser::MxprogContext *context) { auto program = std::make_shared(); program->type = ASTNodeType::Program; program->start_line = context->getStart()->getLine(); program->start_char_pos = context->getStart()->getCharPositionInLine(); program->end_line = context->getStop()->getLine(); program->end_char_pos = context->getStop()->getCharPositionInLine(); auto cur_scope = std::make_shared(); program->current_scope = cur_scope; nodetype_stk.push_back({ASTNodeType::Program, cur_scope}); for (auto def : context->children) { if (auto classDefContext = dynamic_cast(def)) { auto classNode = std::any_cast>(visit(classDefContext)); program->classes.push_back(classNode); program->sorted_children.push_back(classNode); } else if (auto defineStmtContext = dynamic_cast(def)) { auto defineNode = std::dynamic_pointer_cast( std::any_cast>(visit(defineStmtContext))); program->global_variables.push_back(defineNode); program->sorted_children.push_back(defineNode); } else if (auto funcDefContext = dynamic_cast(def)) { auto funcNode = std::any_cast>(visit(funcDefContext)); program->functions.push_back(funcNode); program->sorted_children.push_back(funcNode); } else if (auto EOFToken = dynamic_cast(def)) { if (EOFToken == context->EOF()) break; throw std::runtime_error("unknown subnode occurred in visitMxprog"); } else { throw std::runtime_error("unknown subnode occurred in visitMxprog"); } } nodetype_stk.pop_back(); return program; } std::any Visitor::visitFunction_def(MXParser::Function_defContext *context) { auto func = std::make_shared(); func->type = ASTNodeType::FuncDef; func->is_constructor = false; func->start_line = context->getStart()->getLine(); func->start_char_pos = context->getStart()->getCharPositionInLine(); func->end_line = context->getStop()->getLine(); func->end_char_pos = context->getStop()->getCharPositionInLine(); auto cur_scope = std::make_shared(); cur_scope->parent = nodetype_stk.back().second.get(); func->current_scope = cur_scope; nodetype_stk.push_back({ASTNodeType::FuncDef, func->current_scope}); std::string return_type_str; if (auto type_context = dynamic_cast(context->children[0])) { // return type return_type_str = type_context->getText(); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "return_type_str=" << return_type_str << std::endl; } else throw std::runtime_error("unknown subnode occurred in visitFunction_def"); int return_dimensions = 0; for (size_t i = 1; i < context->children.size(); i++) { if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::ID) { break; } return_dimensions++; } return_dimensions >>= 1; if (return_dimensions == 0) { func->return_type = return_type_str; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded return type is [none-array]" << return_type_str << std::endl; } else { func->return_type = ArrayType{true, return_type_str, static_cast(return_dimensions)}; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded return type is [array]" << return_type_str << " with dimensions=" << return_dimensions << std::endl; } cur_scope->schema.return_type = func->return_type; func->func_name = context->children[1 + 2 * return_dimensions]->getText(); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "func_name=" << func->func_name << std::endl; size_t cur = 3 + 2 * return_dimensions; bool is_first_para = true; while (true) { if (cur >= context->children.size()) throw std::runtime_error("something strange happened in visitFunction_def"); auto ptr = dynamic_cast(context->children[cur]); if (ptr != nullptr && ptr->getSymbol()->getType() == MXParser::RPAREN) break; if (is_first_para) goto cancel_first; if (ptr->getSymbol()->getType() != MXParser::COMMA) throw std::runtime_error("something strange happened in visitFunction_def"); cur++; cancel_first: is_first_para = false; std::string cur_para_type_base_str = context->children[cur]->getText(); int cur_para_dimensions = 0; while (dynamic_cast(context->children[cur + 1]) != nullptr && (dynamic_cast(context->children[cur + 1])->getSymbol()->getType() == MXParser::LBRACKET || dynamic_cast(context->children[cur + 1])->getSymbol()->getType() == MXParser::RBRACKET)) { cur_para_dimensions++; cur++; } cur++; cur_para_dimensions >>= 1; std::string cur_para_name = context->children[cur]->getText(); ExprTypeInfo cur_para_type; if (cur_para_dimensions == 0) { cur_para_type = cur_para_type_base_str; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded parameter type is [none-array]" << cur_para_type_base_str << std::endl; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded parameter name is " << cur_para_name << std::endl; } else { cur_para_type = ArrayType{true, cur_para_type_base_str, static_cast(cur_para_dimensions)}; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded parameter type is [array]" << cur_para_type_base_str << " with dimensions=" << cur_para_dimensions << std::endl; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded parameter name is " << cur_para_name << std::endl; } func->params.push_back(std::make_pair(cur_para_name, cur_para_type)); cur_scope->schema.arguments.push_back(std::make_pair(cur_para_type, cur_para_name)); cur++; } if (ClassDefScope *cparent = dynamic_cast(cur_scope->parent)) { if (!cparent->add_function(func->func_name, cur_scope)) { throw SemanticError("Function name " + func->func_name + " is not available", 1); } } else if (GlobalScope *gparent = dynamic_cast(cur_scope->parent)) { if (!gparent->add_function(func->func_name, cur_scope)) { throw SemanticError("Function name " + func->func_name + " is not available", 1); } } else throw std::runtime_error("unknown parent scope type"); func->func_body = std::dynamic_pointer_cast( std::any_cast>(visit(context->suite()))); nodetype_stk.pop_back(); return func; } std::any Visitor::visitClass_def(MXParser::Class_defContext *context) { auto class_def = std::make_shared(); class_def->type = ASTNodeType::ClassDef; class_def->start_line = context->getStart()->getLine(); class_def->start_char_pos = context->getStart()->getCharPositionInLine(); class_def->end_line = context->getStop()->getLine(); class_def->end_char_pos = context->getStop()->getCharPositionInLine(); auto cur_scope = std::make_shared(); cur_scope->parent = nodetype_stk.back().second.get(); class_def->current_scope = cur_scope; GlobalScope *gparent = dynamic_cast(cur_scope->parent); assert(gparent != nullptr); if (!gparent->add_class(context->ID()->getText(), cur_scope)) { throw SemanticError("Class name " + context->ID()->getText() + " is not available", 1); } nodetype_stk.push_back({ASTNodeType::ClassDef, class_def->current_scope}); class_def->class_name = context->ID()->getText(); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "building a class named " << class_def->class_name << std::endl; // std::vector constructors = context->class_constructor(); if (context->class_constructor().size() > 1) throw SemanticError("Multiple constructor found for class " + class_def->class_name, 2); // if (constructors.size() > 0) // class_def->constructor = std::any_cast>(visit(constructors[0])); // std::vector functions = context->function_def(); // for (auto func : functions) { // auto func_node = std::any_cast>(visit(func)); // class_def->member_functions.push_back(func_node); // } // std::vector vars = context->class_var_def(); // for (auto var : vars) { // auto var_node = std::dynamic_pointer_cast( // std::any_cast>(visit(var))); // class_def->member_variables.push_back(var_node); // } for (size_t i = 3; i < context->children.size(); i++) { if (auto var_def_ctx = dynamic_cast(context->children[i])) { auto var_node = std::dynamic_pointer_cast( std::any_cast>(visit(context->children[i]))); class_def->member_variables.push_back(var_node); class_def->sorted_children.push_back(var_node); } else if (auto constructor_ctx = dynamic_cast(context->children[i])) { auto constructor_node = std::any_cast>(visit(context->children[i])); class_def->constructor = constructor_node; class_def->sorted_children.push_back(constructor_node); } else if (auto func_def_ctx = dynamic_cast(context->children[i])) { auto func_node = std::any_cast>(visit(context->children[i])); class_def->member_functions.push_back(func_node); class_def->sorted_children.push_back(func_node); } else break; } nodetype_stk.pop_back(); return class_def; } std::any Visitor::visitClass_var_def(MXParser::Class_var_defContext *context) { auto member_var_def = std::make_shared(); member_var_def->type = ASTNodeType::ClassVariable; member_var_def->start_line = context->getStart()->getLine(); member_var_def->start_char_pos = context->getStart()->getCharPositionInLine(); member_var_def->end_line = context->getStop()->getLine(); member_var_def->end_char_pos = context->getStop()->getCharPositionInLine(); member_var_def->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::ClassVariable, member_var_def->current_scope}); std::string define_type_base; if (auto type_context = dynamic_cast(context->children[0])) { define_type_base = type_context->getText(); } else throw std::runtime_error("unknown subnode occurred in visitClass_var_def"); int define_dimensions = 0; for (size_t i = 1; i < context->children.size(); i++) { if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::ID) { break; } define_dimensions++; } define_dimensions >>= 1; if (define_dimensions == 0) { member_var_def->var_type = define_type_base; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded member variable type is [none-array]" << define_type_base << std::endl; } else { member_var_def->var_type = ArrayType{true, define_type_base, static_cast(define_dimensions)}; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded member variable type is [array]" << define_type_base << " with dimensions=" << define_dimensions << std::endl; } auto identifiers = context->ID(); for (auto id : identifiers) { member_var_def->vars.push_back(std::make_pair(id->getText(), nullptr)); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded member variable name is " << id->getText() << std::endl; if (!member_var_def->current_scope->add_variable(id->getText(), member_var_def->var_type)) { throw SemanticError("Variable name " + id->getText() + " is not available", 1); } } nodetype_stk.pop_back(); return std::static_pointer_cast(member_var_def); } std::any Visitor::visitClass_constructor(MXParser::Class_constructorContext *context) { auto construct_func = std::make_shared(); construct_func->type = ASTNodeType::Constructor; construct_func->is_constructor = false; construct_func->start_line = context->getStart()->getLine(); construct_func->start_char_pos = context->getStart()->getCharPositionInLine(); construct_func->end_line = context->getStop()->getLine(); construct_func->end_char_pos = context->getStop()->getCharPositionInLine(); auto cur_scope = std::make_shared(); cur_scope->parent = nodetype_stk.back().second.get(); construct_func->current_scope = cur_scope; construct_func->func_name = context->ID()->getText(); cur_scope->schema.return_type = "void"; nodetype_stk.push_back({ASTNodeType::Constructor, construct_func->current_scope}); construct_func->func_body = std::dynamic_pointer_cast( std::any_cast>(visit(context->suite()))); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "constructor body visited" << std::endl; nodetype_stk.pop_back(); return construct_func; } std::any Visitor::visitSuite(MXParser::SuiteContext *context) { auto suite_node = std::make_shared(); suite_node->type = ASTNodeType::SuiteStatement; suite_node->start_line = context->getStart()->getLine(); suite_node->start_char_pos = context->getStart()->getCharPositionInLine(); suite_node->end_line = context->getStop()->getLine(); suite_node->end_char_pos = context->getStop()->getCharPositionInLine(); auto cur_scope = std::make_shared(); cur_scope->parent = nodetype_stk.back().second.get(); suite_node->current_scope = cur_scope; assert(nodetype_stk.size() > 0); cur_scope->parent = nodetype_stk.back().second.get(); nodetype_stk.push_back({ASTNodeType::SuiteStatement, cur_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding suite statements" << std::endl; std::vector stmts = context->statement(); for (auto stmt : stmts) { auto stmt_node = std::any_cast>(visit(stmt)); suite_node->statements.push_back(stmt_node); } nodetype_stk.pop_back(); return std::static_pointer_cast(suite_node); } std::any Visitor::visitEmpty_statement(MXParser::Empty_statementContext *context) { auto stmt = std::make_shared(); stmt->type = ASTNodeType::EmptyStatement; stmt->start_line = context->getStart()->getLine(); stmt->start_char_pos = context->getStart()->getCharPositionInLine(); stmt->end_line = context->getStop()->getLine(); stmt->end_char_pos = context->getStop()->getCharPositionInLine(); return std::static_pointer_cast(stmt); } std::any Visitor::visitDefinition_statement(MXParser::Definition_statementContext *context) { return visit(context->define_statement()); } std::any Visitor::visitExpr_statement(MXParser::Expr_statementContext *context) { auto expr_stmt = std::make_shared(); expr_stmt->type = ASTNodeType::ExprStatement; expr_stmt->start_line = context->getStart()->getLine(); expr_stmt->start_char_pos = context->getStart()->getCharPositionInLine(); expr_stmt->end_line = context->getStop()->getLine(); expr_stmt->end_char_pos = context->getStop()->getCharPositionInLine(); assert(nodetype_stk.size() > 0); expr_stmt->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::ExprStatement, expr_stmt->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding an expression statement" << std::endl; expr_stmt->expr = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(expr_stmt); } std::any Visitor::visitIf_statement(MXParser::If_statementContext *context) { auto if_stmt = std::make_shared(); if_stmt->type = ASTNodeType::IfStatement; if_stmt->start_line = context->getStart()->getLine(); if_stmt->start_char_pos = context->getStart()->getCharPositionInLine(); if_stmt->end_line = context->getStop()->getLine(); if_stmt->end_char_pos = context->getStop()->getCharPositionInLine(); assert(nodetype_stk.size() > 0); if_stmt->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::IfStatement, if_stmt->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding an if statement" << std::endl; if_stmt->condition = std::any_cast>(visit(context->expr())); std::vector sub_stmts = context->statement(); if_stmt->if_clause = std::any_cast>(visit(sub_stmts[0])); if (sub_stmts.size() > 1) { if_stmt->has_else_clause = true; if_stmt->else_clause = std::any_cast>(visit(sub_stmts[1])); } else { if_stmt->has_else_clause = false; if_stmt->else_clause = nullptr; } nodetype_stk.pop_back(); return std::static_pointer_cast(if_stmt); } std::any Visitor::visitWhile_statement(MXParser::While_statementContext *context) { auto while_stmt = std::make_shared(); while_stmt->type = ASTNodeType::WhileStatement; while_stmt->start_line = context->getStart()->getLine(); while_stmt->start_char_pos = context->getStart()->getCharPositionInLine(); while_stmt->end_line = context->getStop()->getLine(); while_stmt->end_char_pos = context->getStop()->getCharPositionInLine(); assert(nodetype_stk.size() > 0); while_stmt->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::WhileStatement, while_stmt->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding a while statement" << std::endl; while_stmt->condition = std::any_cast>(visit(context->expr())); while_stmt->loop_body = std::any_cast>(visit(context->statement())); nodetype_stk.pop_back(); return std::static_pointer_cast(while_stmt); } std::any Visitor::visitFor_statement(MXParser::For_statementContext *context) { auto for_stmt = std::make_shared(); for_stmt->type = ASTNodeType::ForStatement; for_stmt->start_line = context->getStart()->getLine(); for_stmt->start_char_pos = context->getStart()->getCharPositionInLine(); for_stmt->end_line = context->getStop()->getLine(); for_stmt->end_char_pos = context->getStop()->getCharPositionInLine(); auto cur_scope = std::make_shared(); cur_scope->parent = nodetype_stk.back().second.get(); for_stmt->current_scope = cur_scope; nodetype_stk.push_back({ASTNodeType::ForStatement, for_stmt->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding a for statement" << std::endl; size_t cur = 2; if (dynamic_cast(context->children[cur]) != nullptr && dynamic_cast(context->children[cur])->getSymbol()->getType() == MXParser::SEMICOLON) { for_stmt->initial = nullptr; cur += 1; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "initial is empty" << std::endl; } else if (dynamic_cast(context->children[cur]) != nullptr) { for_stmt->initial = std::dynamic_pointer_cast( std::any_cast>(visit(context->children[cur]))); cur += 1; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "initial is a define statement" << std::endl; } else if (dynamic_cast(context->children[cur]) != nullptr) { auto expr = std::any_cast>(visit(context->children[cur])); auto expr_stmt = std::make_shared(); expr_stmt->type = ASTNodeType::ExprStatement; expr_stmt->start_line = expr->start_line; expr_stmt->start_char_pos = expr->start_char_pos; expr_stmt->end_line = expr->end_line; expr_stmt->end_char_pos = expr->end_char_pos; expr_stmt->expr = expr; for_stmt->initial = std::static_pointer_cast(expr_stmt); cur += 2; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "initial is an expression statement" << std::endl; } else { throw std::runtime_error("unknown subnode occurred in visitFor_statement"); } if (dynamic_cast(context->children[cur]) != nullptr && dynamic_cast(context->children[cur])->getSymbol()->getType() == MXParser::SEMICOLON) { for_stmt->condition = nullptr; cur += 1; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "condition is empty" << std::endl; } else { for_stmt->condition = std::any_cast>(visit(context->children[cur])); cur += 2; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "condition is an expression" << std::endl; } if (dynamic_cast(context->children[cur]) != nullptr) { auto expr = std::any_cast>(visit(context->children[cur])); auto expr_stmt = std::make_shared(); expr_stmt->type = ASTNodeType::ExprStatement; expr_stmt->start_line = expr->start_line; expr_stmt->start_char_pos = expr->start_char_pos; expr_stmt->end_line = expr->end_line; expr_stmt->end_char_pos = expr->end_char_pos; expr_stmt->expr = expr; for_stmt->update = std::static_pointer_cast(expr_stmt); cur += 2; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "update is an expression statement" << std::endl; } else if (dynamic_cast(context->children[cur]) != nullptr && dynamic_cast(context->children[cur])->getSymbol()->getType() == MXParser::RPAREN) { std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "update is empty" << std::endl; for_stmt->update = nullptr; cur += 1; } else { throw std::runtime_error("unknown subnode occurred in visitFor_statement"); } for_stmt->loop_body = std::any_cast>(visit(context->statement())); nodetype_stk.pop_back(); return std::static_pointer_cast(for_stmt); } std::any Visitor::visitJmp_statement(MXParser::Jmp_statementContext *context) { auto jmp_stmt = std::make_shared(); jmp_stmt->type = ASTNodeType::JmpStatement; jmp_stmt->start_line = context->getStart()->getLine(); jmp_stmt->start_char_pos = context->getStart()->getCharPositionInLine(); jmp_stmt->end_line = context->getStop()->getLine(); jmp_stmt->end_char_pos = context->getStop()->getCharPositionInLine(); assert(nodetype_stk.size() > 0); jmp_stmt->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::JmpStatement, jmp_stmt->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding a jmp statement" << std::endl; if (context->RETURN() != nullptr) { jmp_stmt->jmp_type = 0; if (context->expr() != nullptr) { jmp_stmt->return_value = std::any_cast>(visit(context->expr())); } else { jmp_stmt->return_value = nullptr; } } else if (context->BREAK() != nullptr) { jmp_stmt->jmp_type = 1; jmp_stmt->return_value = nullptr; } else if (context->CONTINUE() != nullptr) { jmp_stmt->jmp_type = 2; jmp_stmt->return_value = nullptr; } else { throw std::runtime_error("unknown jmp statement type"); } nodetype_stk.pop_back(); return std::static_pointer_cast(jmp_stmt); } std::any Visitor::visitSuite_statement(MXParser::Suite_statementContext *context) { return visit(context->suite()); } std::any Visitor::visitDefine_statement(MXParser::Define_statementContext *context) { // define_statement : type (LBRACKET RBRACKET)* ID (ASSIGN expr)? (COMMA ID (ASSIGN expr)?)* SEMICOLON; auto def_stmt = std::make_shared(); def_stmt->type = ASTNodeType::DefinitionStatement; def_stmt->start_line = context->getStart()->getLine(); def_stmt->start_char_pos = context->getStart()->getCharPositionInLine(); def_stmt->end_line = context->getStop()->getLine(); def_stmt->end_char_pos = context->getStop()->getCharPositionInLine(); assert(nodetype_stk.size() > 0); def_stmt->current_scope = nodetype_stk.back().second; if (nodetype_stk.size() > 0 && (nodetype_stk.back().first == ASTNodeType::IfStatement || nodetype_stk.back().first == ASTNodeType::WhileStatement || nodetype_stk.back().first == ASTNodeType::ForStatement)) { def_stmt->current_scope = std::make_shared(); def_stmt->current_scope->parent = nodetype_stk.back().second.get(); } nodetype_stk.push_back({ASTNodeType::DefinitionStatement, def_stmt->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding a definition statement" << std::endl; std::string define_type_base; if (auto type_context = dynamic_cast(context->children[0])) { define_type_base = type_context->getText(); } else throw std::runtime_error("unknown subnode occurred in visitDefine_statement"); size_t define_dimensions = 0; for (size_t i = 1; i < context->children.size(); i++) { if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::ID) { break; } define_dimensions++; } define_dimensions >>= 1; if (define_dimensions == 0) { def_stmt->var_type = define_type_base; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded variable type is [none-array]" << define_type_base << std::endl; } else { def_stmt->var_type = ArrayType{true, define_type_base, static_cast(define_dimensions)}; std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded variable type is [array]" << define_type_base << " with dimensions=" << define_dimensions << std::endl; } for (size_t i = 1 + 2 * define_dimensions; i < context->children.size();) { if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::SEMICOLON) { break; } if (i != 1 + 2 * define_dimensions) i++; if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::ID) { def_stmt->vars.push_back(std::make_pair(context->children[i]->getText(), nullptr)); // if (!def_stmt->current_scope->add_variable(context->children[i]->getText(), def_stmt->var_type)) // throw SemanticError("Variable " + context->children[i]->getText() + " already defined", 1); } else throw std::runtime_error("unknown subnode occurred in visitDefine_statement"); i++; if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::ASSIGN) { i++; def_stmt->vars.back().second = std::any_cast>(visit(context->children[i])); i++; } } nodetype_stk.pop_back(); return std::static_pointer_cast(def_stmt); } std::any Visitor::visitGgll_expression(MXParser::Ggll_expressionContext *context) { auto ggll_expr = std::make_shared(); ggll_expr->type = ASTNodeType::GGLLExpr; ggll_expr->start_line = context->getStart()->getLine(); ggll_expr->start_char_pos = context->getStart()->getCharPositionInLine(); ggll_expr->end_line = context->getStop()->getLine(); ggll_expr->end_char_pos = context->getStop()->getCharPositionInLine(); assert(nodetype_stk.size() > 0); ggll_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::GGLLExpr, ggll_expr->current_scope}); ggll_expr->op = context->children[1]->getText(); ggll_expr->left = std::any_cast>(visit(context->children[0])); ggll_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(ggll_expr); } std::any Visitor::visitBxor_expression(MXParser::Bxor_expressionContext *context) { auto bxor_expr = std::make_shared(); bxor_expr->type = ASTNodeType::BXorExpr; bxor_expr->start_line = context->getStart()->getLine(); bxor_expr->start_char_pos = context->getStart()->getCharPositionInLine(); bxor_expr->end_line = context->getStop()->getLine(); bxor_expr->end_char_pos = context->getStop()->getCharPositionInLine(); bxor_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::BXorExpr, bxor_expr->current_scope}); bxor_expr->op = context->children[1]->getText(); bxor_expr->left = std::any_cast>(visit(context->children[0])); bxor_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(bxor_expr); } std::any Visitor::visitSuffix_expression(MXParser::Suffix_expressionContext *context) { auto suffix_expr = std::make_shared(); suffix_expr->type = ASTNodeType::SuffixExpr; suffix_expr->start_line = context->getStart()->getLine(); suffix_expr->start_char_pos = context->getStart()->getCharPositionInLine(); suffix_expr->end_line = context->getStop()->getLine(); suffix_expr->end_char_pos = context->getStop()->getCharPositionInLine(); suffix_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::SuffixExpr, suffix_expr->current_scope}); suffix_expr->op = context->children[1]->getText(); suffix_expr->base = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(suffix_expr); } std::any Visitor::visitLand_expression(MXParser::Land_expressionContext *context) { auto land_expr = std::make_shared(); land_expr->type = ASTNodeType::LAndExpr; land_expr->start_line = context->getStart()->getLine(); land_expr->start_char_pos = context->getStart()->getCharPositionInLine(); land_expr->end_line = context->getStop()->getLine(); land_expr->end_char_pos = context->getStop()->getCharPositionInLine(); land_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::LAndExpr, land_expr->current_scope}); land_expr->op = context->children[1]->getText(); land_expr->left = std::any_cast>(visit(context->children[0])); land_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(land_expr); } std::any Visitor::visitPm_expression(MXParser::Pm_expressionContext *context) { auto pm_expr = std::make_shared(); pm_expr->type = ASTNodeType::PMExpr; pm_expr->start_line = context->getStart()->getLine(); pm_expr->start_char_pos = context->getStart()->getCharPositionInLine(); pm_expr->end_line = context->getStop()->getLine(); pm_expr->end_char_pos = context->getStop()->getCharPositionInLine(); pm_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::PMExpr, pm_expr->current_scope}); pm_expr->op = context->children[1]->getText(); pm_expr->left = std::any_cast>(visit(context->children[0])); pm_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(pm_expr); } std::any Visitor::visitIndex_expression(MXParser::Index_expressionContext *context) { auto idx_expr = std::make_shared(); idx_expr->type = ASTNodeType::IndexExpr; idx_expr->start_line = context->getStart()->getLine(); idx_expr->start_char_pos = context->getStart()->getCharPositionInLine(); idx_expr->end_line = context->getStop()->getLine(); idx_expr->end_char_pos = context->getStop()->getCharPositionInLine(); idx_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::IndexExpr, idx_expr->current_scope}); auto sub_exprs = context->expr(); idx_expr->base = std::any_cast>(visit(sub_exprs[0])); for (size_t i = 1; i < sub_exprs.size(); i++) { idx_expr->indices.push_back(std::any_cast>(visit(sub_exprs[i]))); } nodetype_stk.pop_back(); return std::static_pointer_cast(idx_expr); } std::any Visitor::visitOpposite_expression(MXParser::Opposite_expressionContext *context) { auto oppsite_expr = std::make_shared(); oppsite_expr->type = ASTNodeType::OppositeExpr; oppsite_expr->start_line = context->getStart()->getLine(); oppsite_expr->start_char_pos = context->getStart()->getCharPositionInLine(); oppsite_expr->end_line = context->getStop()->getLine(); oppsite_expr->end_char_pos = context->getStop()->getCharPositionInLine(); oppsite_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::OppositeExpr, oppsite_expr->current_scope}); oppsite_expr->base = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(oppsite_expr); } std::any Visitor::visitNew_array_expression(MXParser::New_array_expressionContext *context) { auto new_array = std::make_shared(); new_array->type = ASTNodeType::NewArrayExpr; new_array->start_line = context->getStart()->getLine(); new_array->start_char_pos = context->getStart()->getCharPositionInLine(); new_array->end_line = context->getStop()->getLine(); new_array->end_char_pos = context->getStop()->getCharPositionInLine(); new_array->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::NewArrayExpr, new_array->current_scope}); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "Adding a new array expression" << std::endl; size_t total_dimensions = context->LBRACKET().size(); std::string base_type = context->type()->getText(); new_array->expr_type_info = ArrayType{true, base_type, total_dimensions}; size_t total_dim_count = 0; bool dim_size_specified = false; bool dim_with_size_end = false; new_array->dim_size.resize(total_dimensions); for (size_t i = 3; i < context->children.size() && total_dim_count < total_dimensions; i++) { if (dynamic_cast(context->children[i]) != nullptr && dynamic_cast(context->children[i])->getSymbol()->getType() == MXParser::RBRACKET) { total_dim_count++; if (!dim_size_specified) { dim_with_size_end = true; } dim_size_specified = false; } else if (dynamic_cast(context->children[i]) != nullptr) { new_array->dim_size[total_dim_count] = std::any_cast>(visit(context->children[i])); std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "dim " << total_dim_count << " has size " << std::endl; dim_size_specified = true; if (dim_with_size_end) { throw SemanticError("The shape of multidimensional array must be specified from left to right.", 1); } } } if (context->constant() != nullptr) { new_array->has_initial_value = true; new_array->initial_value = std::dynamic_pointer_cast( std::any_cast>(visit(context->constant()))); } else new_array->has_initial_value = false; nodetype_stk.pop_back(); return std::static_pointer_cast(new_array); } std::any Visitor::visitBasic_expression(MXParser::Basic_expressionContext *context) { return visit(context->basic_expr()); } std::any Visitor::visitAccess_expression(MXParser::Access_expressionContext *context) { auto access_expr = std::make_shared(); access_expr->start_line = context->getStart()->getLine(); access_expr->start_char_pos = context->getStart()->getCharPositionInLine(); access_expr->end_line = context->getStop()->getLine(); access_expr->end_char_pos = context->getStop()->getCharPositionInLine(); if (context->LPAREN() == nullptr) { access_expr->type = ASTNodeType::MemberVariableAccessExpr; access_expr->is_function = false; } else { access_expr->type = ASTNodeType::MemberFunctionAccessExpr; access_expr->is_function = true; } access_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({access_expr->type, access_expr->current_scope}); auto sub_exprs = context->expr(); access_expr->base = std::any_cast>(visit(sub_exprs[0])); access_expr->member = context->ID()->getText(); for (size_t i = 1; i < sub_exprs.size(); i++) { access_expr->arguments.push_back(std::any_cast>(visit(sub_exprs[i]))); } nodetype_stk.pop_back(); return std::static_pointer_cast(access_expr); } std::any Visitor::visitBand_expression(MXParser::Band_expressionContext *context) { auto band_expr = std::make_shared(); band_expr->type = ASTNodeType::BAndExpr; band_expr->start_line = context->getStart()->getLine(); band_expr->start_char_pos = context->getStart()->getCharPositionInLine(); band_expr->end_line = context->getStop()->getLine(); band_expr->end_char_pos = context->getStop()->getCharPositionInLine(); band_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::BAndExpr, band_expr->current_scope}); band_expr->op = context->children[1]->getText(); band_expr->left = std::any_cast>(visit(context->children[0])); band_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(band_expr); } std::any Visitor::visitNew_construct_expression(MXParser::New_construct_expressionContext *context) { auto new_construct_expr = std::make_shared(); new_construct_expr->type = ASTNodeType::NewConstructExpr; new_construct_expr->start_line = context->getStart()->getLine(); new_construct_expr->start_char_pos = context->getStart()->getCharPositionInLine(); new_construct_expr->end_line = context->getStop()->getLine(); new_construct_expr->end_char_pos = context->getStop()->getCharPositionInLine(); new_construct_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::NewConstructExpr, new_construct_expr->current_scope}); new_construct_expr->expr_type_info = context->type()->getText(); nodetype_stk.pop_back(); return std::static_pointer_cast(new_construct_expr); } std::any Visitor::visitTernary_expression(MXParser::Ternary_expressionContext *context) { auto ternary_expr = std::make_shared(); ternary_expr->type = ASTNodeType::TernaryExpr; ternary_expr->start_line = context->getStart()->getLine(); ternary_expr->start_char_pos = context->getStart()->getCharPositionInLine(); ternary_expr->end_line = context->getStop()->getLine(); ternary_expr->end_char_pos = context->getStop()->getCharPositionInLine(); ternary_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::TernaryExpr, ternary_expr->current_scope}); auto expr_subnodes = context->expr(); ternary_expr->condition = std::any_cast>(visit(expr_subnodes[0])); ternary_expr->src1 = std::any_cast>(visit(expr_subnodes[1])); ternary_expr->src2 = std::any_cast>(visit(expr_subnodes[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(ternary_expr); } std::any Visitor::visitBnot_expression(MXParser::Bnot_expressionContext *context) { auto bnot_expr = std::make_shared(); bnot_expr->type = ASTNodeType::BNotExpr; bnot_expr->start_line = context->getStart()->getLine(); bnot_expr->start_char_pos = context->getStart()->getCharPositionInLine(); bnot_expr->end_line = context->getStop()->getLine(); bnot_expr->end_char_pos = context->getStop()->getCharPositionInLine(); bnot_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::BNotExpr, bnot_expr->current_scope}); bnot_expr->base = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(bnot_expr); } std::any Visitor::visitLnot_expression(MXParser::Lnot_expressionContext *context) { auto lnot_expr = std::make_shared(); lnot_expr->type = ASTNodeType::LNotExpr; lnot_expr->start_line = context->getStart()->getLine(); lnot_expr->start_char_pos = context->getStart()->getCharPositionInLine(); lnot_expr->end_line = context->getStop()->getLine(); lnot_expr->end_char_pos = context->getStop()->getCharPositionInLine(); lnot_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::LNotExpr, lnot_expr->current_scope}); lnot_expr->base = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(lnot_expr); } std::any Visitor::visitPrefix_expression(MXParser::Prefix_expressionContext *context) { auto prefix_expr = std::make_shared(); prefix_expr->type = ASTNodeType::PrefixExpr; prefix_expr->start_line = context->getStart()->getLine(); prefix_expr->start_char_pos = context->getStart()->getCharPositionInLine(); prefix_expr->end_line = context->getStop()->getLine(); prefix_expr->end_char_pos = context->getStop()->getCharPositionInLine(); prefix_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::PrefixExpr, prefix_expr->current_scope}); prefix_expr->op = context->children[0]->getText(); prefix_expr->base = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(prefix_expr); } std::any Visitor::visitRl_expression(MXParser::Rl_expressionContext *context) { auto rl_expr = std::make_shared(); rl_expr->type = ASTNodeType::RLExpr; rl_expr->start_line = context->getStart()->getLine(); rl_expr->start_char_pos = context->getStart()->getCharPositionInLine(); rl_expr->end_line = context->getStop()->getLine(); rl_expr->end_char_pos = context->getStop()->getCharPositionInLine(); rl_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::RLExpr, rl_expr->current_scope}); rl_expr->op = context->children[1]->getText(); rl_expr->left = std::any_cast>(visit(context->children[0])); rl_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(rl_expr); } std::any Visitor::visitAssign_expression(MXParser::Assign_expressionContext *context) { auto assign_expr = std::make_shared(); assign_expr->type = ASTNodeType::AssignExpr; assign_expr->start_line = context->getStart()->getLine(); assign_expr->start_char_pos = context->getStart()->getCharPositionInLine(); assign_expr->end_line = context->getStop()->getLine(); assign_expr->end_char_pos = context->getStop()->getCharPositionInLine(); assign_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::AssignExpr, assign_expr->current_scope}); assign_expr->dest = std::any_cast>(visit(context->expr(0))); assign_expr->src = std::any_cast>(visit(context->expr(1))); nodetype_stk.pop_back(); return std::static_pointer_cast(assign_expr); } std::any Visitor::visitMdm_expression(MXParser::Mdm_expressionContext *context) { auto mdm_expr = std::make_shared(); mdm_expr->type = ASTNodeType::MDMExpr; mdm_expr->start_line = context->getStart()->getLine(); mdm_expr->start_char_pos = context->getStart()->getCharPositionInLine(); mdm_expr->end_line = context->getStop()->getLine(); mdm_expr->end_char_pos = context->getStop()->getCharPositionInLine(); mdm_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::MDMExpr, mdm_expr->current_scope}); mdm_expr->op = context->children[1]->getText(); mdm_expr->left = std::any_cast>(visit(context->children[0])); mdm_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(mdm_expr); } std::any Visitor::visitNew_expression(MXParser::New_expressionContext *context) { auto new_expr = std::make_shared(); new_expr->type = ASTNodeType::NewExpr; new_expr->start_line = context->getStart()->getLine(); new_expr->start_char_pos = context->getStart()->getCharPositionInLine(); new_expr->end_line = context->getStop()->getLine(); new_expr->end_char_pos = context->getStop()->getCharPositionInLine(); new_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::NewExpr, new_expr->current_scope}); new_expr->expr_type_info = context->type()->getText(); nodetype_stk.pop_back(); return std::static_pointer_cast(new_expr); } std::any Visitor::visitNe_expression(MXParser::Ne_expressionContext *context) { auto ne_expr = std::make_shared(); ne_expr->type = ASTNodeType::NEExpr; ne_expr->start_line = context->getStart()->getLine(); ne_expr->start_char_pos = context->getStart()->getCharPositionInLine(); ne_expr->end_line = context->getStop()->getLine(); ne_expr->end_char_pos = context->getStop()->getCharPositionInLine(); ne_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::NEExpr, ne_expr->current_scope}); ne_expr->op = context->children[1]->getText(); ne_expr->left = std::any_cast>(visit(context->children[0])); ne_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(ne_expr); } std::any Visitor::visitBor_expression(MXParser::Bor_expressionContext *context) { auto bor_expr = std::make_shared(); bor_expr->type = ASTNodeType::BOrExpr; bor_expr->start_line = context->getStart()->getLine(); bor_expr->start_char_pos = context->getStart()->getCharPositionInLine(); bor_expr->end_line = context->getStop()->getLine(); bor_expr->end_char_pos = context->getStop()->getCharPositionInLine(); bor_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::BOrExpr, bor_expr->current_scope}); bor_expr->op = context->children[1]->getText(); bor_expr->left = std::any_cast>(visit(context->children[0])); bor_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(bor_expr); } std::any Visitor::visitLor_expression(MXParser::Lor_expressionContext *context) { auto lor_expr = std::make_shared(); lor_expr->type = ASTNodeType::LOrExpr; lor_expr->start_line = context->getStart()->getLine(); lor_expr->start_char_pos = context->getStart()->getCharPositionInLine(); lor_expr->end_line = context->getStop()->getLine(); lor_expr->end_char_pos = context->getStop()->getCharPositionInLine(); lor_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::LOrExpr, lor_expr->current_scope}); lor_expr->op = context->children[1]->getText(); lor_expr->left = std::any_cast>(visit(context->children[0])); lor_expr->right = std::any_cast>(visit(context->children[2])); nodetype_stk.pop_back(); return std::static_pointer_cast(lor_expr); } std::any Visitor::visitThis_expr(MXParser::This_exprContext *context) { auto this_expr = std::make_shared(); this_expr->type = ASTNodeType::ThisExpr; this_expr->start_line = context->getStart()->getLine(); this_expr->start_char_pos = context->getStart()->getCharPositionInLine(); this_expr->end_line = context->getStop()->getLine(); this_expr->end_char_pos = context->getStop()->getCharPositionInLine(); this_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::ThisExpr, this_expr->current_scope}); nodetype_stk.pop_back(); return std::static_pointer_cast(this_expr); } std::any Visitor::visitParen_expr(MXParser::Paren_exprContext *context) { auto paren_expr = std::make_shared(); paren_expr->type = ASTNodeType::ParenExpr; paren_expr->start_line = context->getStart()->getLine(); paren_expr->start_char_pos = context->getStart()->getCharPositionInLine(); paren_expr->end_line = context->getStop()->getLine(); paren_expr->end_char_pos = context->getStop()->getCharPositionInLine(); paren_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::ParenExpr, paren_expr->current_scope}); paren_expr->expr = std::any_cast>(visit(context->expr())); nodetype_stk.pop_back(); return std::static_pointer_cast(paren_expr); } std::any Visitor::visitId_expr(MXParser::Id_exprContext *context) { auto id_expr = std::make_shared(); id_expr->type = ASTNodeType::IDExpr; id_expr->start_line = context->getStart()->getLine(); id_expr->start_char_pos = context->getStart()->getCharPositionInLine(); id_expr->end_line = context->getStop()->getLine(); id_expr->end_char_pos = context->getStop()->getCharPositionInLine(); id_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::IDExpr, id_expr->current_scope}); id_expr->id = IdentifierType{context->ID()->getText()}; nodetype_stk.pop_back(); return std::static_pointer_cast(id_expr); } std::any Visitor::visitFunction_call_expr(MXParser::Function_call_exprContext *context) { auto func_call_expr = std::make_shared(); func_call_expr->type = ASTNodeType::FunctionCallExpr; func_call_expr->start_line = context->getStart()->getLine(); func_call_expr->start_char_pos = context->getStart()->getCharPositionInLine(); func_call_expr->end_line = context->getStop()->getLine(); func_call_expr->end_char_pos = context->getStop()->getCharPositionInLine(); func_call_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::FunctionCallExpr, func_call_expr->current_scope}); func_call_expr->func_name = IdentifierType{context->ID()->getText()}; auto expr_subnodes = context->expr(); for (auto expr_subnode : expr_subnodes) { func_call_expr->arguments.push_back(std::any_cast>(visit(expr_subnode))); } nodetype_stk.pop_back(); return std::static_pointer_cast(func_call_expr); } std::any Visitor::visitFormatted_string_expr(MXParser::Formatted_string_exprContext *context) { return visit(context->formatted_string()); } std::any Visitor::visitConstant_expr(MXParser::Constant_exprContext *context) { return visit(context->constant()); } std::any Visitor::visitFormatted_string(MXParser::Formatted_stringContext *context) { auto fmt_expr = std::make_shared(); fmt_expr->type = ASTNodeType::FormattedStringExpr; fmt_expr->start_line = context->getStart()->getLine(); fmt_expr->start_char_pos = context->getStart()->getCharPositionInLine(); fmt_expr->end_line = context->getStop()->getLine(); fmt_expr->end_char_pos = context->getStop()->getCharPositionInLine(); fmt_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::FormattedStringExpr, fmt_expr->current_scope}); if (context->FORMAT_STRING_WHOLE() != nullptr) { fmt_expr->literals.push_back(context->FORMAT_STRING_WHOLE()->getText()); } else { auto expr_subnodes = context->expr(); auto body_subnodes = context->FORMAT_STRING_BODY(); fmt_expr->literals.push_back(context->FORMAT_STRING_HEAD()->getText()); for (size_t i = 0; i < body_subnodes.size(); i++) { fmt_expr->literals.push_back(body_subnodes[i]->getText()); } fmt_expr->literals.push_back(context->FORMAT_STRING_TAIL()->getText()); for (auto expr_subnode : expr_subnodes) { fmt_expr->exprs.push_back(std::any_cast>(visit(expr_subnode))); } } nodetype_stk.pop_back(); return std::static_pointer_cast(fmt_expr); } std::any Visitor::visitConstant(MXParser::ConstantContext *context) { auto constant_expr = std::make_shared(); constant_expr->type = ASTNodeType::ConstantExpr; constant_expr->start_line = context->getStart()->getLine(); constant_expr->start_char_pos = context->getStart()->getCharPositionInLine(); constant_expr->end_line = context->getStop()->getLine(); constant_expr->end_char_pos = context->getStop()->getCharPositionInLine(); constant_expr->current_scope = nodetype_stk.back().second; nodetype_stk.push_back({ASTNodeType::ConstantExpr, constant_expr->current_scope}); if (context->TRUE() != nullptr || context->FALSE() != nullptr) { constant_expr->expr_type_info = "bool"; if (context->TRUE()) constant_expr->value = true; else constant_expr->value = false; constant_expr->level = 0; } else if (context->INT_LITERAL() != nullptr) { constant_expr->expr_type_info = "int"; constant_expr->value = static_cast(std::stoull(context->INT_LITERAL()->getText())); constant_expr->level = 0; } else if (context->STRING_LITERAL() != nullptr) { constant_expr->expr_type_info = "string"; constant_expr->value = context->STRING_LITERAL()->getText(); constant_expr->level = 0; } else if (context->NULL_() != nullptr) { constant_expr->expr_type_info = "null"; constant_expr->value = NullType(); constant_expr->level = 0; } else if (context->LBRACE() != nullptr) { // array constant auto sub_constants = context->constant(); size_t max_sub_level = 0; std::vector> tmp; for (auto sub_constant : sub_constants) { auto sub_constant_expr = std::dynamic_pointer_cast( std::any_cast>(visit(sub_constant))); max_sub_level = std::max(max_sub_level, std::dynamic_pointer_cast(sub_constant_expr)->level); tmp.push_back(sub_constant_expr); } constant_expr->value = std::move(tmp); constant_expr->level = max_sub_level + 1; } else { throw std::runtime_error("unknown constant type"); } nodetype_stk.pop_back(); return std::static_pointer_cast(constant_expr); } std::any Visitor::visitType(MXParser::TypeContext *context) { throw std::runtime_error("Visitor::visitType should not be called"); }