From 6106ca91e8866f5b7dead9ab0d2a564c805fe201 Mon Sep 17 00:00:00 2001 From: Mattias Ajander <mattias@ajander.se> Date: Mon, 7 Apr 2025 23:55:08 +0200 Subject: [PATCH] Improved arg parser, updated README and new error messages. --- .vscode/settings.json | 4 ++- README.md | 52 +++++++++++++++++++++++++++------------ source/main.cc | 12 ++++++++- source/utils/ArgParser.cc | 19 +++++++------- source/utils/Common.cc | 3 ++- 5 files changed, 61 insertions(+), 29 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2596dbe..26b8047 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -75,6 +75,8 @@ "cinttypes": "cpp", "typeinfo": "cpp", "valarray": "cpp", - "variant": "cpp" + "variant": "cpp", + "*.def": "cpp", + "*.inc": "cpp" } } diff --git a/README.md b/README.md index 51e560d..3b44e90 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,10 @@ Funk is a custom programming language with its own interpreter. It was developed - Static typing system - Built-in error handling - Comprehensive logging system + - REPL for interactive programming ## Project Structure -```zsh +```sh funk/ ├── .vscode/ # VSCode settings and configurations ├── bin/ # Binary files (generated by make) @@ -19,20 +20,24 @@ funk/ │ └── funk # Main Funk interpreter ├── build/ # Object files (generated by make) ├── docs/ # Documentation +│ ├── Language Specification/ # Typst documents for language specification │ ├── Language Specification.pdf # Formal language specification │ └── html/ # Generated Doxygen documentation (after generation) +├── examples/ # Example programs ├── include/ # Header files +│ ├── ast/ # Abstract syntax tree │ ├── lexer/ # Lexical analysis components +│ ├── logging/ # Logging implementation │ ├── parser/ # Syntax analysis components -│ └── ... # Other headers +│ ├── token/ # Token implementation +│ └── utils/ # Utility functions ├── source/ # Source code -│ ├── lexer/ # Lexer implementation -│ ├── parser/ # Parser implementation -│ └── ... # Other implementations +│ ├── main.cc # Main entry point +│ └── ... # Same structure as include/ ├── tests/ # Test files for each major feature ├── .clang-format # Clang format configuration -├── Doxyfile # Doxygen configuration file ├── compile+test # Script to compile and run all tests +├── Doxyfile # Doxygen configuration file ├── funk.log # Log file (created during execution) └── Makefile # Build system configuration ``` @@ -48,38 +53,53 @@ funk/ ### Building from Source 1. Clone the repository: -```zsh +```sh git clone https://gitlab.liu.se/mataj513/tdp019.git cd tdp019 ``` 2. Build the interpreter: -```zsh +```sh make ``` 3. For a clean build: -```zsh +```sh make clean make ``` +4. For testing: +```sh +make tests +``` + ## Usage After building the Funk interpreter, you can use it in the following ways: ### Running Funk Programs To execute a Funk program file: -```zsh -./bin/funk <path_to_file> +```sh +./bin/funk <path_to_file> [args] ``` See examples in the [examples](examples) directory. +Arguments can be passed to the program by adding them after the file path. Arguments before the file path are interpreted as arguments to the interpreter itself. + For more help and options see: -```zsh +```sh ./bin/funk --help ``` +### REPL + +The interpreter also supports a REPL (Read-Eval-Print-Loop) mode, allowing you to interactively enter and execute Funk code. + +```sh +./bin/funk +``` + ### Logging The interpreter uses a logging system to provide detailed information about its execution. The log file is located at `funk.log` but can be changed by adding `--log new/path.log` to the program. @@ -88,17 +108,17 @@ The log file is located at `funk.log` but can be changed by adding `--log new/pa Funk comes with a comprehensive test suite to ensure functionality: 1. Run all tests (compiles and executes tests): -```zsh +```sh ./compile+test ``` 2. Compile tests only: -```zsh +```sh make tests ``` 3. Run a specific test: -```zsh +```sh ./bin/tests/<name> ``` @@ -109,7 +129,7 @@ See the [Language Specification](docs/Language%20Specification.pdf) for a formal ### Doxygen Documentation To generate the detailed documentation, run the following command: -```zsh +```sh doxygen Doxyfile ``` diff --git a/source/main.cc b/source/main.cc index 5457394..611dffa 100644 --- a/source/main.cc +++ b/source/main.cc @@ -19,7 +19,7 @@ using namespace funk; */ HashMap<String, String> options{ {"--help", "Display this help message"}, - {"--log <file>", "Set the log file"}, + {"--log=<file>", "Set the log file"}, {"--debug", "Enable debug logging"}, {"--ast", "Log the AST representation"}, {"--tokens", "Log the lexical tokens"}, @@ -123,6 +123,16 @@ void process_file(const String& file, const Config& config, const Vector<String> LOG_ERROR("Error processing file " + file + ": " + e.what()); cerr << "Error: " << e.trace() << endl; } + catch (const FileError& e) + { + LOG_ERROR(e.what()); + cerr << e.what() << endl; + } + catch (const std::exception& e) + { + LOG_ERROR("Unknown error occurred: " + String(e.what())); + cerr << "Unknown error occurred: " << e.what() << endl; + } } /** diff --git a/source/utils/ArgParser.cc b/source/utils/ArgParser.cc index be6475d..268bc1e 100644 --- a/source/utils/ArgParser.cc +++ b/source/utils/ArgParser.cc @@ -9,20 +9,19 @@ ArgParser::ArgParser(int argc, char* argv[]) { String arg{argv[i]}; - if (arg.substr(0, 2) == "--") + if (!file.empty()) { - if (i + 1 < argc && argv[i + 1][0] != '-') - { - options[arg] = argv[i + 1]; - ++i; - } - else { options[arg] = ""; } + args.push_back(arg); + continue; } - else + + if (arg.substr(0, 2) == "--") { - if (file.empty()) { file = arg; } - else { args.push_back(arg); } + size_t eq_pos = arg.find('='); + if (eq_pos != String::npos) { options[arg.substr(0, eq_pos)] = arg.substr(eq_pos + 1); } + else { options[arg] = ""; } } + else { file = arg; } } } diff --git a/source/utils/Common.cc b/source/utils/Common.cc index 3d709d7..35b6c1e 100644 --- a/source/utils/Common.cc +++ b/source/utils/Common.cc @@ -1,4 +1,5 @@ #include "utils/Common.h" +#include "utils/Exception.h" namespace funk { @@ -6,7 +7,7 @@ namespace funk String read_file(const String& filename) { std::ifstream file(filename); - if (!file.is_open()) { throw std::runtime_error("Failed to open file: " + filename); } + if (!file.is_open()) { throw FileError("Failed to open file: " + filename); } std::stringstream buffer; buffer << file.rdbuf() << '\n'; return buffer.str(); -- GitLab