diff --git a/.vscode/settings.json b/.vscode/settings.json index 2596dbe49465108c3ccf40fabfc86cb35df7d698..26b8047dde4ab111ac517bac523a1e4666bcaa6d 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 51e560d137c45c66389faa6c35942702e44dc214..3b44e90edaca66bc4b00a665d7a0f6f63c1dd809 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 54573944adcd1243b905969e9f8a7851f177e898..611dffaf0edc9551bbccc634d9bde941b352d855 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 be6475dc7cfa327e6417c8113a615df8e71f0350..268bc1e5bb0edcc8d1fc54a7ef9ca615561fd4aa 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 3d709d706a5427864b2aaa07db6488405343affb..35b6c1e4883d85f1cd2b6fb53b823c6341640714 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();