From a2d493279b0996b9009a18cdb2cdf278c16d039f Mon Sep 17 00:00:00 2001 From: Clement Doucy Date: Sat, 24 Aug 2024 17:31:09 +0200 Subject: [PATCH] Added readme.md --- .gitignore | 1 + CMakeLists.txt | 2 +- Makefile | 6 +- README.md | 189 ++++++++++++++++++- doc/grammar.md | 48 ----- examples/hello_world.hu | 1 + {tst => tests}/CMakeLists.txt | 2 +- {tst => tests}/evaluator/evaluator_test.cpp | 0 {tst => tests}/evaluator/statements_test.cpp | 0 {tst => tests}/lexer/lexer_test.cpp | 0 {tst => tests}/parser/parser_error_test.cpp | 0 {tst => tests}/parser/parser_test.cpp | 0 tests/tst.cmake | 9 + tst/tst.cmake | 9 - 14 files changed, 202 insertions(+), 65 deletions(-) delete mode 100644 doc/grammar.md create mode 100644 examples/hello_world.hu rename {tst => tests}/CMakeLists.txt (95%) rename {tst => tests}/evaluator/evaluator_test.cpp (100%) rename {tst => tests}/evaluator/statements_test.cpp (100%) rename {tst => tests}/lexer/lexer_test.cpp (100%) rename {tst => tests}/parser/parser_error_test.cpp (100%) rename {tst => tests}/parser/parser_test.cpp (100%) create mode 100644 tests/tst.cmake delete mode 100644 tst/tst.cmake diff --git a/.gitignore b/.gitignore index a798d19..1e95faf 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ .idea/ cmake-build-*/ interpreter +hudson-interpreter diff --git a/CMakeLists.txt b/CMakeLists.txt index b638cb4..56587a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ set(CMAKE_CXX_FLAGS "-std=c++20 -Wpedantic -Wall -Wextra ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g3 ${CMAKE_CXX_FLAGS_DEBUG}") if (${CMAKE_BUILD_TYPE} STREQUAL "test") - add_subdirectory(tst) + add_subdirectory(tests) return() endif() diff --git a/Makefile b/Makefile index 998777c..019ed4d 100644 --- a/Makefile +++ b/Makefile @@ -3,21 +3,21 @@ all: build build: cmake -DCMAKE_BUILD_TYPE=debug -G "Unix Makefiles" -B cmake-build-debug make -C cmake-build-debug - cp cmake-build-debug/interpreter . + cp cmake-build-debug/interpreter ./hudson-interpreter test: cmake -DCMAKE_BUILD_TYPE=test -G "Unix Makefiles" -B cmake-build-test make -C cmake-build-test run-test: test - ./cmake-build-test/tst/interpreter-test + ./cmake-build-test/tests/interpreter-test coverage: gcovr -e "tst/" -e "cmake-build-test/" clean-build: rm -rf cmake-build-debug - rm -f ./interpreter + rm -f ./hudson-interpreter clean-test: rm -rf cmake-build-test diff --git a/README.md b/README.md index e6bc524..3ab1a2c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,187 @@ -[![Continuous Integration](https://github.com/cdoucy/interpreter/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/cdoucy/interpreter/actions/workflows/ci.yaml) +[![Unit tests](https://github.com/cdoucy/interpreter/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/cdoucy/interpreter/actions/workflows/ci.yaml) -# interpreter -Interpreter implementation in C++ +# Hudson Programming Language + +Welcome to the Hudson programming language! Hudson is a simple, yet powerful, programming language. This project is designed to be a learning tool for both language design and implementation, focusing on a clear, minimalistic syntax and core programming constructs. + +This repository contains the complete specification of the Hudson programming language and the implementation of its interpreter in C++. + +## Table of Contents + +- [Overview](#overview) +- [Features](#features) +- [Installation](#installation) +- [Usage](#usage) +- [Examples](#examples) +- [Testing](#examples) +- [Grammar](#grammar) +- [Contributing](#contributing) +- [License](#license) + +## Overview + +Hudson is a programming language that draws inspiration from several other languages while maintaining its own unique approach to syntax and semantics. It is statically typed and imperative, with a focus on simplicity and readability. This project aims to provide a foundation for further exploration into language design and interpreter construction. + +## Features + +- **Simple Syntax**: Hudson has a clean and minimalistic syntax that is easy to understand. +- **Basic Control Structures**: Supports `if`, `while`, `for` loops, and `break`/`continue` statements. +- **Functions**: Allows defining and invoking functions, including anonymous functions. +- **Expressions**: Includes a variety of expressions with support for logical, bitwise, and arithmetic operations. +- **Variable Declarations and Assignments**: Supports variable declarations with optional initialization and compound assignment operations. +- **Increment and Decrement Operators**: `++` and `--` are supported for quick variable updates. +- **Printing**: Built-in `print` statement for output. + +## Installation + +To build and run the Hudson language interpreter: + +1. **Clone the repository**: + ```bash + git clone https://github.com/cdoucy/hudson-lang.git + cd hudson-lang + ``` + +2. **Build the project**: + Ensure you have CMake installed, then run: + ```bash + make + ``` + This will generate the Hudson interpreter executable. + +3. **Run a Hudson program**: + ```bash + ./hudson-interpreter examples/hello_world.hu + ``` + +## Usage + +You can create Hudson source files with the `.hu` extension and run them using the Hudson interpreter. Here's a basic example of a Hudson program: + +```hudson +int x = 10; +int y = 20; +print(x + y); +``` + +## Examples + +Here are some examples of what you can do in Hudson: + +### Hello World + +```hudson +print("Hello, World!"); +``` + +### Loops and Conditionals + +```hudson +int i = 0; +while (i < 5) { + print(i); + i++; +} +if (i == 5) { + print("Done!"); +} else { + print("Something went wrong."); +} +``` + +### Functions and Recursion + +```hudson +fnc factorial(n int) int { + if (n == 0) { + return 1; + } else { + return n * factorial(n - 1); + } +} + +int result = factorial(5); +print(result); +``` + +## Testing + +The Hudson programming language interpreter has been developed using Test-Driven Development (TDD) to ensure high-quality and reliable code. You can run unit tests and check code coverage with the following commands: + +1. **Run the Unit Tests**: + To run all the unit tests for the Hudson interpreter, use the following command: + + ```bash + make run-test + ``` +This command will execute all unit tests and display the results in the terminal. + +2. **Check Coverage**: To check the code coverage of the unit tests, use the command: + To run all the unit tests for the Hudson interpreter, use the following command: + + ```bash + make coverage + ``` +This command will generate a coverage report, showing how much of the codebase is covered by the tests. Reviewing this report can help identify untested parts of the code and ensure comprehensive test coverage. + +## Grammar + +The specification of the Hudson programming language in EBNF (Extended Backus-Naur Form) notation is as follows: + +```ebnf +program = { stmt } +stmt = expr_stmt | declaration | assignment | inc_dec | return + | break | continue | print | block | while + | for | if | function +expr_stmt = expr ";" +declaration = type ident [ "=" expr ] ";" +assignment = ident ( "=" | "+=" | "+-" | "*=" | "%=" | "/+" ) expr ";" +inc_dec = ident ( "++" | "--" ) ";" +return = "return" [ expr ] ";" +break = "break" ";" +continue = "continue" ";" +print = "print" "(" [ expr ] ")" ";" +block = "{" { stmt } "}" +while = "while" "(" expr ")" ( stmt | ";" ) +for = "for" "(" [ declaration | assignment ] ";" expr ";" assignment | inc_dec ")" ( smt | ";" ) +if = "if" "(" expr ")" stmt [ "else" stmt ] +function = "fnc" ident fnc_signature block +expr = or +or = and { "||" and } +and = bitwise_or { "&&" bitwise_or } +bitwise_or = bitwise_xor { "|" bitwise_xor } +bitwise_xor = bitwise_and { "^" bitwise_and } +bitwise_and = equality { "&" equality } +equality = comparison { "==" | "!=" comparison } +comparison = bitshift { "<" | "<=" | ">" | ">=" bitshift } +bitshift = term { ">>" | "<<" term } +term = factor { "-" | "+" factor } +factor = unary { "/" | "*" | "%" unary } +unary = ( "+" | "-" | "!" | "~" ) unary | call +call = primary { "(" [ params ] ")" } +primary = int_lit | ident | string_lit | anonymous_fnc | grouping +grouping = "(" expr ")" + +params = expr { "," expr } +anonymous_fnc = 'fnc' fnc_signature block +fnc_signature = "(" [ ident type { "," ident type } ] ")" [ type ] +type = "int" | "str" | "fnc" | fnc_signature +ident = ( letter | "_" ) { letter | digit | "_" } +int_lit = digit | { digit } +string_lit = '"' { * } '"' +letter = "A" ... " Z" | "a" ... "z" +digit = "0" ... "9" +``` + +## Credits + +This project was inspired by the book [Crafting Interpreters](https://craftinginterpreters.com/) by Robert Nystrom. The book provided valuable insights into the design and implementation of interpreters, which greatly influenced the development of the Hudson programming language. + + +## Contributing + +Contributions are welcome! If you have ideas for improvements or new features, feel free to open an issue or submit a pull request. Please make sure to follow the coding standards used in the project and include tests where applicable. + +## License + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. diff --git a/doc/grammar.md b/doc/grammar.md deleted file mode 100644 index c76a411..0000000 --- a/doc/grammar.md +++ /dev/null @@ -1,48 +0,0 @@ -# Grammar - -The specification of the Hudson programming language in EBNF notation is the following : - -```ebnf -program = { stmt } -stmt = expr_stmt | declaration | assignment | inc_dec | return - | break | continue | print | block | while - | for | if | function -expr_stmt = expr ";" -declaration = type ident [ "=" expr ] ";" -assignment = ident ( "=" | "+=" | "+-" | "*=" | "%=" | "/+" ) expr ";" -inc_dec = ident ( "++" | "--" ) ";" -return = "return" [ expr ] ";" -break = "break" ";" -continue = "continue" ";" -print = "print" "(" [ expr ] ")" ";" -block = "{" { stmt } "}" -while = "while" "(" expr ")" ( stmt | ";" ) -for = "for" "(" [ declaration | assignment ] ";" expr ";" assignment | inc_dec ")" ( smt | ";" ) -if = "if" "(" expr ")" stmt [ "else" stmt ] -function = "fnc" ident fnc_signature block -expr = or -or = and { "||" and } -and = bitwise_or { "&&" bitwise_or } -bitwise_or = bitwise_xor { "|" bitwise_xor } -bitwise_xor = bitwise_and { "^" bitwise_and } -bitwise_and = equality { "&" equality } -equality = comparison { "==" | "!=" comparison } -comparison = bitshift { "<" | "<=" | ">" | ">=" bitshift } -bitshift = term { ">>" | "<<" term } -term = factor { "-" | "+" factor } -factor = unary { "/" | "*" | "%" unary } -unary = ( "+" | "-" | "!" | "~" ) unary | call -call = primary { "(" [ params ] ")" } -primary = int_lit | ident | string_lit | anonymous_fnc | grouping -grouping = "(" expr ")" - -params = expr { "," expr } -anonymous_fnc = 'fnc' fnc_signature block -fnc_signature = "(" [ ident type { "," ident type } ] ")" [ type ] -type = "int" | "str" | "fnc" | fnc_signature -ident = ( letter | "_" ) { letter | digit | "_" } -int_lit = digit | { digit } -string_lit = '"' { * } '"' -letter = "A" ... " Z" | "a" ... "z" -digit = "0" ... "9" -``` \ No newline at end of file diff --git a/examples/hello_world.hu b/examples/hello_world.hu new file mode 100644 index 0000000..defc677 --- /dev/null +++ b/examples/hello_world.hu @@ -0,0 +1 @@ +print("Hello world!"); diff --git a/tst/CMakeLists.txt b/tests/CMakeLists.txt similarity index 95% rename from tst/CMakeLists.txt rename to tests/CMakeLists.txt index 71548cf..5afb19b 100644 --- a/tst/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,7 +9,7 @@ set(TARGET interpreter-test) set (PROJECT_ROOT ./..) include(${PROJECT_ROOT}/src/src.cmake) include(${PROJECT_ROOT}/inc/inc.cmake) -include(${PROJECT_ROOT}/tst/tst.cmake) +include(${PROJECT_ROOT}/tests/tst.cmake) include(FetchContent) FetchContent_Declare( diff --git a/tst/evaluator/evaluator_test.cpp b/tests/evaluator/evaluator_test.cpp similarity index 100% rename from tst/evaluator/evaluator_test.cpp rename to tests/evaluator/evaluator_test.cpp diff --git a/tst/evaluator/statements_test.cpp b/tests/evaluator/statements_test.cpp similarity index 100% rename from tst/evaluator/statements_test.cpp rename to tests/evaluator/statements_test.cpp diff --git a/tst/lexer/lexer_test.cpp b/tests/lexer/lexer_test.cpp similarity index 100% rename from tst/lexer/lexer_test.cpp rename to tests/lexer/lexer_test.cpp diff --git a/tst/parser/parser_error_test.cpp b/tests/parser/parser_error_test.cpp similarity index 100% rename from tst/parser/parser_error_test.cpp rename to tests/parser/parser_error_test.cpp diff --git a/tst/parser/parser_test.cpp b/tests/parser/parser_test.cpp similarity index 100% rename from tst/parser/parser_test.cpp rename to tests/parser/parser_test.cpp diff --git a/tests/tst.cmake b/tests/tst.cmake new file mode 100644 index 0000000..8d36eaa --- /dev/null +++ b/tests/tst.cmake @@ -0,0 +1,9 @@ +set( + TEST_SOURCES + + ${PROJECT_ROOT}/tests/lexer/lexer_test.cpp + ${PROJECT_ROOT}/tests/evaluator/evaluator_test.cpp + ${PROJECT_ROOT}/tests/evaluator/statements_test.cpp + ${PROJECT_ROOT}/tests/parser/parser_test.cpp + ${PROJECT_ROOT}/tests/parser/parser_error_test.cpp +) \ No newline at end of file diff --git a/tst/tst.cmake b/tst/tst.cmake deleted file mode 100644 index cd81736..0000000 --- a/tst/tst.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set( - TEST_SOURCES - - ${PROJECT_ROOT}/tst/lexer/lexer_test.cpp - ${PROJECT_ROOT}/tst/evaluator/evaluator_test.cpp - ${PROJECT_ROOT}/tst/evaluator/statements_test.cpp - ${PROJECT_ROOT}/tst/parser/parser_test.cpp - ${PROJECT_ROOT}/tst/parser/parser_error_test.cpp -) \ No newline at end of file