ready to merge docs

This commit is contained in:
2024-08-11 08:37:17 +00:00
parent 9900d5aaf3
commit 22d18436fa
10 changed files with 346 additions and 38 deletions

View File

@ -1,16 +1,205 @@
#include "visitor.h"
#include <stdexcept>
#include <type_traits>
#include "MXParser.h"
#include "MXParserVisitor.h"
#include "ast/ast.h"
std::any Visitor::visitMxprog(MXParser::MxprogContext *context) { throw std::runtime_error("Not implemented"); }
std::any Visitor::visitFunction_def(MXParser::Function_defContext *context) {
throw std::runtime_error("Not implemented");
std::any Visitor::visitMxprog(MXParser::MxprogContext *context) {
auto program = std::make_shared<Program_ASTNode>();
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();
nodetype_stk.push_back(ASTNodeType::Program);
for (auto def : context->children) {
if (auto classDefContext = dynamic_cast<MXParser::Class_defContext *>(def)) {
auto classNode = std::any_cast<std::shared_ptr<ClassDef_ASTNode>>(visit(classDefContext));
program->classes.push_back(classNode);
} else if (auto defineStmtContext = dynamic_cast<MXParser::Define_statementContext *>(def)) {
auto defineNode = std::any_cast<std::shared_ptr<DefinitionStatement_ASTNode>>(visit(defineStmtContext));
program->global_variables.push_back(defineNode);
} else if (auto funcDefContext = dynamic_cast<MXParser::Function_defContext *>(def)) {
auto funcNode = std::any_cast<std::shared_ptr<FuncDef_ASTNode>>(visit(funcDefContext));
program->functions.push_back(funcNode);
} else if (auto EOFToken = dynamic_cast<antlr4::tree::TerminalNode *>(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<FuncDef_ASTNode>();
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();
nodetype_stk.push_back(ASTNodeType::FuncDef);
std::string return_type_str;
if (auto type_context = dynamic_cast<MXParser::TypeContext *>(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<antlr4::tree::TerminalNode *>(context->children[i]) != nullptr &&
dynamic_cast<antlr4::tree::TerminalNode *>(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<size_t>(return_dimensions)};
std::cerr << std::string(nodetype_stk.size() * 2, ' ') << "recorded return type is [array]" << return_type_str
<< " with dimensions=" << return_dimensions << std::endl;
}
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<antlr4::tree::TerminalNode *>(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<antlr4::tree::TerminalNode *>(context->children[cur + 1]) != nullptr &&
(dynamic_cast<antlr4::tree::TerminalNode *>(context->children[cur + 1])->getSymbol()->getType() ==
MXParser::LBRACKET ||
dynamic_cast<antlr4::tree::TerminalNode *>(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<size_t>(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++;
}
func->func_body = std::any_cast<std::shared_ptr<SuiteStatement_ASTNode>>(visit(context->suite()));
nodetype_stk.pop_back();
return func;
}
std::any Visitor::visitClass_def(MXParser::Class_defContext *context) {
auto class_def = std::make_shared<ClassDef_ASTNode>();
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();
nodetype_stk.push_back(ASTNodeType::ClassDef);
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<MXParser::Class_constructorContext *> constructors = context->class_constructor();
if (constructors.size() > 1) throw SemanticError("Multiple constructor found for class " + class_def->class_name, 2);
if (constructors.size() > 0)
class_def->constructor = std::any_cast<std::shared_ptr<FuncDef_ASTNode>>(visit(constructors[0]));
std::vector<MXParser::Function_defContext *> functions = context->function_def();
for (auto func : functions) {
auto func_node = std::any_cast<std::shared_ptr<FuncDef_ASTNode>>(visit(func));
class_def->member_functions.push_back(func_node);
}
nodetype_stk.pop_back();
return class_def;
}
std::any Visitor::visitClass_def(MXParser::Class_defContext *context) { throw std::runtime_error("Not implemented"); }
std::any Visitor::visitClass_var_def(MXParser::Class_var_defContext *context) {
throw std::runtime_error("Not implemented");
auto member_var_def = std::make_shared<DefinitionStatement_ASTNode>();
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();
nodetype_stk.push_back(ASTNodeType::ClassVariable);
std::string define_type_base;
if (auto type_context = dynamic_cast<MXParser::TypeContext *>(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<antlr4::tree::TerminalNode *>(context->children[i]) != nullptr &&
dynamic_cast<antlr4::tree::TerminalNode *>(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<size_t>(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;
}
nodetype_stk.pop_back();
return member_var_def;
}
std::any Visitor::visitClass_constructor(MXParser::Class_constructorContext *context) {
throw std::runtime_error("Not implemented");
auto construct_func = std::make_shared<FuncDef_ASTNode>();
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();
nodetype_stk.push_back(ASTNodeType::Constructor);
construct_func->func_body = std::any_cast<std::shared_ptr<SuiteStatement_ASTNode>>(visit(context->suite()));
nodetype_stk.pop_back();
return construct_func;
}
std::any Visitor::visitSuite(MXParser::SuiteContext *context) { throw std::runtime_error("Not implemented"); }
std::any Visitor::visitEmpty_statement(MXParser::Empty_statementContext *context) {