From 80995caa32c7a9801a03435a668e4bcbc46e777d Mon Sep 17 00:00:00 2001 From: Mattias Ajander <mattias@ajander.se> Date: Mon, 31 Mar 2025 19:24:12 +0200 Subject: [PATCH] Improved main file with tokens, ast and debug settings. --- include/logging/Logger.h | 13 ++++++ source/logging/Logger.cc | 13 +++++- source/main.cc | 94 +++++++++++++++++++++++++++++++++++----- 3 files changed, 107 insertions(+), 13 deletions(-) diff --git a/include/logging/Logger.h b/include/logging/Logger.h index 538de3a..2329866 100644 --- a/include/logging/Logger.h +++ b/include/logging/Logger.h @@ -55,6 +55,18 @@ public: */ void set_file(const std::string& filePath); + /** + * @brief Gets the current log level + * @return LogLevel The current log level + */ + LogLevel get_level() const; + + /** + * @brief Sets the log level + * @param level The log level to set + */ + void set_level(LogLevel level); + /** * @brief Gets the current log file path * @return std::string The current log file path @@ -94,6 +106,7 @@ private: std::string log_path; ///< Path to the log file std::ofstream log_file; ///< Output stream for the log file + LogLevel log_level; ///< Current log level }; /** diff --git a/source/logging/Logger.cc b/source/logging/Logger.cc index 9251d90..90f923f 100644 --- a/source/logging/Logger.cc +++ b/source/logging/Logger.cc @@ -3,7 +3,7 @@ namespace funk { -Logger::Logger() : log_path("funk.log") +Logger::Logger() : log_path("funk.log"), log_level(LogLevel::INFO) { file_open(); } @@ -22,6 +22,7 @@ Logger& Logger::instance() void Logger::log(LogLevel level, const std::string& message) { file_open(); + if (level < log_level) return; auto now = std::chrono::system_clock::now(); auto time = std::chrono::system_clock::to_time_t(now); @@ -60,6 +61,16 @@ std::string Logger::get_file() const return log_path; } +void Logger::set_level(LogLevel level) +{ + log_level = level; +} + +LogLevel Logger::get_level() const +{ + return log_level; +} + void Logger::file_open() { if (log_file.is_open()) return; diff --git a/source/main.cc b/source/main.cc index 4eb5d77..8350180 100644 --- a/source/main.cc +++ b/source/main.cc @@ -5,20 +5,31 @@ using namespace funk; +// Command line options HashMap<String, String> options{ {"--help", "Display this help message"}, {"--log <file>", "Set the log file"}, + {"--debug", "Enable debug logging"}, + {"--ast", "Log the AST representation"}, + {"--tokens", "Log the lexical tokens"}, }; -int main(int argc, char* argv[]) +// Configuration for command line options +struct Config { - ArgParser parser(argc, argv); + bool debug{false}; + bool ast{false}; + bool tokens{false}; +}; +// Process command line arguments and set up logging +bool setup(ArgParser& parser, Config& config) +{ // Print help message - if (argc == 1 || parser.has_option("--help")) + if (parser.has_option("--help")) { cout << ArgParser::help("funk [options] <file>", options) << "\n"; - return 0; + return false; } // Set log file if specified @@ -27,27 +38,86 @@ int main(int argc, char* argv[]) if (!parser.has_value("--log")) { cerr << "No log file specified!\n"; - return 1; + return false; } - logger().set_file(parser.get_option("--log")); } + // Configure logging level + if (parser.has_option("--debug")) + { + config.debug = true; + logger().set_level(LogLevel::DEBUG); + } + // Check if any files were specified if (!parser.has_files()) { cerr << "No files specified!\n"; - return 1; + return false; } - // Lex each file - for (const auto& file : parser.get_files()) + // Set other configuration options + config.ast = parser.has_option("--ast"); + config.tokens = parser.has_option("--tokens"); + + return true; +} + +// Process a single file +void process_file(const String& file, const Config& config) +{ + LOG_INFO("Processing file: " + file); + + try { - Parser parser{Parser::load(file)}; - Node* result{parser.parse()}; + LOG_DEBUG("Lexing file..."); + Lexer lexer{read_file(file), file}; + Vector<Token> tokens{lexer.tokenize()}; + LOG_DEBUG("Tokens lexed!"); + + if (config.tokens) + { + LOG_INFO("Tokens:"); + for (const auto& token : tokens) { LOG_INFO(token); } + } - cout << result->to_s() << " = " << result->evaluate()->to_s() << '\n'; + LOG_DEBUG("Parsing file..."); + Parser parser{tokens, file}; + Node* ast = parser.parse(); + LOG_DEBUG("File parsed!"); + + if (config.ast) { LOG_INFO("AST: " + ast->to_s()); } + + LOG_DEBUG("Evaluating AST..."); + Node* res{ast->evaluate()}; + LOG_DEBUG("AST evaluated!"); + LOG_INFO("Result: " + res->to_s()); + } + catch (const FunkError& e) + { + LOG_ERROR("Error processing file " + file + ": " + e.what()); + cerr << "Error: " << e.trace() << '\n'; + } +} + +int main(int argc, char* argv[]) +{ + ArgParser parser(argc, argv); + Config config; + + // Show help if no arguments provided + if (argc == 1) + { + cout << ArgParser::help("funk [options] <file>", options) << "\n"; + return 0; } + // Setup and validate arguments + if (!setup(parser, config)) { return 1; } + + // Process each file + for (const auto& file : parser.get_files()) { process_file(file, config); } + return 0; } -- GitLab