#include #include #include "antlr4-runtime.h" #include "ProtoParserBaseListener.h" #include "ProtoLexer.h" #include "ProtoParser.h" #include "message.h" #include "service.h" #include "plugins/c/c_message_plugin.h" #include "plugins/c/c_service_server_plugin.h" #include "plugins/c/c_service_client_plugin.h" #include #include #include using namespace tqcq; class Listener : public ProtoParserBaseListener { public: void enterMessageStatement(ProtoParser::MessageStatementContext *context) override { message_stack.push(std::make_shared(context->ID()->getText())); } void exitMessageStatement(ProtoParser::MessageStatementContext *context) override { message_stack.top()->SetItems(std::move(items)); assert(items.empty()); if (message_map.find(message_stack.top()->id()) != message_map.end()) { std::cout << "message " << message_stack.top()->id() << " already exists" << std::endl; exit(1); } message_map.insert(std::make_pair(message_stack.top()->id(), message_stack.top())); message_stack.pop(); } void exitMessageBaseItemStatement(ProtoParser::MessageBaseItemStatementContext *context) override { int idx = std::stoi(context->NUMBER()->getText()); tqcq::Item::Ptr item = nullptr; tqcq::Item::Type item_type = tqcq::Item::Type::kInt32; if (context->INT32()) { item_type = tqcq::Item::Type::kInt32; } else if (context->STRING()){ item_type = tqcq::Item::Type::kString; } else if (context->UINT32()) { item_type = tqcq::Item::Type::kUInt32; } else { assert(false); } item = std::make_shared(item_type, context->ID()->getText(), idx); items.push_back(std::move(item)); } void exitMessageMessageItemStatement(ProtoParser::MessageMessageItemStatementContext *context) override { int idx = std::stoi(context->NUMBER()->getText()); auto message_type = context->ID(0)->getText(); auto message_name = context->ID(1)->getText(); auto item = std::make_shared(tqcq::Item::Type::kMessage, message_name, idx); items.push_back(std::move(item)); } void exitServiceStatement(ProtoParser::ServiceStatementContext *context) override { std::string id = context->ID()->getText(); auto service = std::make_shared(id); service->SetRPCs(std::move(rpcs)); assert(rpcs.empty()); services.push_back(std::move(service)); } void exitRpcStatement(ProtoParser::RpcStatementContext *context) override { std::string id = context->ID(0)->getText(); std::string request_id = context->ID(1)->getText(); std::string response_id = context->ID(2)->getText(); auto rpc = std::make_shared(id, request_id, response_id); rpcs.push_back(std::move(rpc)); } std::map message_map; std::vector items; std::stack message_stack; std::vector rpcs; std::vector services; }; int main(int argc, char *argv[]) { if (argc < 3) { std::cout << "usage: " << argv[0] << " " << std::endl; return 1; } std::string proto_file = argv[1]; std::string output_dir = argv[2]; // show current working directory char cwd[1024]; if (getcwd(cwd, sizeof(cwd)) != NULL) { std::cout << "Current working dir: " << cwd << std::endl; } else { perror("getcwd() error"); return 1; } std::ifstream ifs; ifs.open(proto_file); antlr4::ANTLRInputStream input(ifs); ProtoLexer lexer(&input); antlr4::CommonTokenStream tokens(&lexer); ProtoParser parser(&tokens); // parser.removeErrorListeners(); // Visitor visitor; // visitor.visit(parser.program()); Listener listener; Listener listener2; antlr4::tree::ParseTreeWalker::DEFAULT.walk(&listener, parser.program()); for (const auto& item : listener.message_map) { std::cout << item.second->ToString() << std::endl; } // for (const auto& service : listener.services) { // std::cout << service->ToString() << std::endl; // } tqcq::CMessagePlugin message_plugin(output_dir); message_plugin.Generate(listener.message_map); tqcq::CServiceServerPlugin service_server_plugin(output_dir); service_server_plugin.Generate(listener.services); tqcq::CServiceClientPlugin service_client_plugin(output_dir); service_client_plugin.Generate(listener.services); return 0; }