diff --git a/src/cpp/include/kaira/command.hpp b/src/cpp/include/kaira/command.hpp new file mode 100644 index 0000000000000000000000000000000000000000..32362e6eff9194f98d197f5f9b7822016aadf484 --- /dev/null +++ b/src/cpp/include/kaira/command.hpp @@ -0,0 +1,44 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#ifndef KAIRA_COMMAND_HPP +#define KAIRA_COMMAND_HPP + +#include <kaira/command_kind.hpp> +#include <kaira/flag.hpp> +#include <kaira/option.hpp> +#include <nola/owning_ptr.hpp> +#include <vector> + +namespace kaira { +class command { + +public: + command() = default; + +public: + void set_subcommand(nola::owning_ptr<command> subcommand); + void set_kind(command_kind kind); + void add_option(option option); + void add_flag(flag flag); + void add_argument(std::string argument); + +public: + auto subcommand() const -> nola::owning_ptr<command> const&; + auto kind() const -> command_kind const&; + auto option_array() const -> std::vector<option> const&; + auto flag_array() const -> std::vector<flag> const&; + auto argument_array() const -> std::vector<std::string> const&; + +private: + nola::owning_ptr<command> subcommand_; + command_kind kind_; + std::vector<option> option_array_; + std::vector<flag> flag_array_; + std::vector<std::string> argument_array_; +}; +} // namespace kaira + +#endif // KAIRA_COMMAND_HPP diff --git a/src/cpp/include/kaira/detail/token.hpp b/src/cpp/include/kaira/detail/token.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1df4b88cf71587f8f04af2084bb61cd52bb07192 --- /dev/null +++ b/src/cpp/include/kaira/detail/token.hpp @@ -0,0 +1,52 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#ifndef KAIRA_DETAIL_TOKEN_HPP +#define KAIRA_DETAIL_TOKEN_HPP + +#include <kaira/detail/char_kind.hpp> +#include <kaira/detail/token_kind.hpp> +#include <string> +#include <vector> + +namespace kaira::detail { +// Methods Associated with Fundamental Char Kinds +auto is_char_letter(char c) -> bool; +auto is_char_digit(char c) -> bool; +auto is_char_identifier_symbol(char c) -> bool; +auto is_char_nonidentifier_symbol(char c) -> bool; +auto is_char_whitespace(char c) -> bool; +auto determine_char_kind(char c) -> char_kind; + +// Methods Associated with Composite Char Kinds +auto is_char_character(char c) -> bool; +auto is_char_symbol(char c) -> bool; +auto is_char_alphanum(char c) -> bool; + +// Methods Associated with Fundamental Token Kinds +auto is_identifier(std::string const& token) -> bool; +auto is_nonidentifier(std::string const& token) -> bool; +auto is_key(std::string const& token) -> bool; +auto is_string_literal(std::string const& token) -> bool; +auto determine_token_kind(std::string const& token) -> token_kind; + +class token { +public: + token() = default; + token(std::string value, token_kind kind) : value_{std::move(value)}, kind_{kind} {} + + auto value() const -> std::string const& { return value_; } + auto kind() const -> token_kind const& { return kind_; } + +private: + std::string value_; + token_kind kind_; +}; + +auto lex(std::vector<std::string> const& input_array) -> std::vector<token>; + +} // namespace kaira::detail + +#endif // KAIRA_DETAIL_TOKEN_HPP diff --git a/src/cpp/include/kaira/flag.hpp b/src/cpp/include/kaira/flag.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c23231c5d14ed616665795a0da99228ed35ed1cd --- /dev/null +++ b/src/cpp/include/kaira/flag.hpp @@ -0,0 +1,28 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#ifndef KAIRA_FLAG_HPP +#define KAIRA_FLAG_HPP + +#include <string> + +namespace kaira { +class flag { +public: + flag() = default; + + flag(std::string name, std::string description); + +public: + auto key() const -> std::string const&; + auto description() const -> std::string const&; + +private: + std::string name_; + std::string description_; +}; +} // namespace kaira + +#endif // KAIRA_FLAG_HPP diff --git a/src/cpp/include/kaira/option.hpp b/src/cpp/include/kaira/option.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7a938345b4bc6ceef94d86074be7f3b4cd8c5826 --- /dev/null +++ b/src/cpp/include/kaira/option.hpp @@ -0,0 +1,17 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#ifndef KAIRA_OPTION_HPP +#define KAIRA_OPTION_HPP + +namespace kaira { +class option { + +public: + option() = default; +}; +} // namespace kaira + +#endif // KAIRA_OPTION_HPP diff --git a/src/cpp/include/kaira/parser.hpp b/src/cpp/include/kaira/parser.hpp new file mode 100644 index 0000000000000000000000000000000000000000..13894ccf737dc42c5d6db0b604297d9cc5316a7b --- /dev/null +++ b/src/cpp/include/kaira/parser.hpp @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#ifndef KAIRA_PARSER_HPP +#define KAIRA_PARSER_HPP + +#include <kaira/command_kind.hpp> + +namespace kaira { +class parser { +public: + parser() = default; + parser(std::string name, std::string description); + +private: + std::string name_; + std::string description_; + command_kind kind_; +}; +} // namespace kaira + +#endif // KAIRA_PARSER_HPP diff --git a/src/cpp/lib/kaira/detail/token.cpp b/src/cpp/lib/kaira/detail/token.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17f3aa72f0990cd0b261bf1e0b35d2a4629e7feb --- /dev/null +++ b/src/cpp/lib/kaira/detail/token.cpp @@ -0,0 +1,164 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#include <algorithm> +#include <cctype> +#include <kaira/detail/token.hpp> + +namespace kaira::detail { +auto is_char_letter(char c) -> bool +{ + + return ( + c == 'a' or c == 'b' or c == 'c' or c == 'd' or c == 'e' or // + c == 'f' or c == 'g' or c == 'h' or c == 'i' or c == 'j' or // + c == 'k' or c == 'l' or c == 'm' or c == 'n' or c == 'o' or // + c == 'p' or c == 'q' or c == 'r' or c == 's' or c == 't' or // + c == 'u' or c == 'v' or c == 'w' or c == 'x' or c == 'y' or // + c == 'z' // + or c == 'A' or c == 'B' or c == 'C' or c == 'D' or c == 'E' // + or c == 'F' or c == 'G' or c == 'H' or c == 'I' or c == 'J' // + or c == 'K' or c == 'L' or c == 'M' or c == 'N' or c == 'O' // + or c == 'P' or c == 'Q' or c == 'R' or c == 'S' or c == 'T' // + or c == 'U' or c == 'V' or c == 'W' or c == 'X' or c == 'Y' // + or c == 'Z'); +} + +auto is_char_digit(char c) -> bool +{ + return ( + c == '0' or c == '1' or c == '2' or c == '3' or c == '4' or // + c == '5' or c == '6' or c == '7' or c == '8' or c == '9'); +} + +auto is_char_identifier_symbol(char c) -> bool +{ + return (c == '.' or c == '-' or c == '_'); +} + +auto is_char_nonidentifier_symbol(char c) -> bool +{ + return ( + c == '%' or c == '*' or c == '+' or c == ',' or c == '/' or // + c == ':' or c == '=' or c == '?' or c == '|' or c == '@' or // + c == '#' or c == '!' or c == '\'' or c == '$' or c == '&' or // + c == '\"' or c == '(' or c == '}' or c == ')' or c == ';' or // + c == '<' or c == '>' or c == '[' or c == '\\' or c == ']' or // + c == '^' or c == '`' or c == '{' or c == '~'); +} + +auto is_char_whitespace(char c) -> bool +{ + return (c == ' ' or c == '\t' or c == '\n' or c == '\r'); +} + +auto determine_char_kind(char c) -> char_kind +{ + if (is_char_letter(c)) { + return char_kind::letter; + } + + if (is_char_digit(c)) { + return char_kind::digit; + } + + if (is_char_identifier_symbol(c)) { + return char_kind::identifier_symbol; + } + + if (is_char_nonidentifier_symbol(c)) { + return char_kind::nonidentifier_symbol; + } + + if (is_char_whitespace(c)) { + return char_kind::wschar; + } + + return char_kind::unknown; +} + +auto is_char_character(char c) -> bool +{ + return determine_char_kind(c) != char_kind::unknown; +} + +auto is_char_symbol(char c) -> bool +{ + auto const kind = determine_char_kind(c); + return kind == char_kind::nonidentifier_symbol or kind == char_kind::identifier_symbol; +} + +auto is_char_alphanum(char c) -> bool +{ + auto const kind = determine_char_kind(c); + return kind == char_kind::letter or kind == char_kind::digit; +} + +auto is_identifier(std::string const& token) -> bool +{ + return std::all_of(token.begin(), token.end(), [](char c) { + return is_char_alphanum(c) or is_char_identifier_symbol(c); + }); +} + +auto is_nonidentifier(std::string const& token) -> bool +{ + auto const first_part = std::all_of( + token.begin(), token.end(), [](char c) { return is_char_alphanum(c) or is_char_symbol(c); }); + + auto const second_part = not is_identifier(token); + return first_part and second_part; +} + +auto is_key(std::string const& token) -> bool +{ + return token[0] == '-' and token[1] == '-' and is_identifier(token.substr(2)); +} + +auto is_string_literal(std::string const& token) -> bool +{ + auto first_part + = std::all_of(token.begin(), token.end(), [](char c) { return is_char_character(c); }); + + auto second_part = not(is_identifier(token) or is_nonidentifier(token) or is_key(token)); + + return first_part and second_part; +} + +auto determine_token_kind(std::string const& token) -> token_kind +{ + if (is_key(token)) { + return token_kind::key; + } + + if (is_identifier(token)) { + return token_kind::identifier; + } + + if (is_nonidentifier(token)) { + return token_kind::nonidentifier; + } + + if (is_string_literal(token)) { + return token_kind::string_literal; + } + + return token_kind::unknown; +} + +auto lex(std::vector<std::string> const& input_array) -> std::vector<token> +{ + std::vector<token> result; + result.reserve(input_array.size()); + + for (auto const& value : input_array) { + auto const kind = determine_token_kind(value); + result.emplace_back(value, kind); + } + + return result; +} + +} // namespace kaira::detail diff --git a/src/jnum/kaira/command_kind.jnum b/src/jnum/kaira/command_kind.jnum new file mode 100644 index 0000000000000000000000000000000000000000..14060de40ae89d11b5f7963163f90a9bb8638a77 --- /dev/null +++ b/src/jnum/kaira/command_kind.jnum @@ -0,0 +1,24 @@ +{ + "copyright" : + { + "license" : "Apache-2.0", + "author_array" : + [ + { + "year" : "2023", + "name" : "Jayesh Badwaik", + "email" : "j.badwaik@fz-juelich.de" + } + ] + }, + "header_array" : [ ], + "typename" : "kaira::command_kind", + "underlying_type" : "std::size_t", + "option_map" : + { + "simple" : "0", + "reduced" : "1", + "super": "2" + }, + "default_option" : "simple" +} diff --git a/src/jnum/kaira/detail/char_kind.jnum b/src/jnum/kaira/detail/char_kind.jnum new file mode 100644 index 0000000000000000000000000000000000000000..9d0c27bd3a5d44b8f4a06924363cba374c08f0d5 --- /dev/null +++ b/src/jnum/kaira/detail/char_kind.jnum @@ -0,0 +1,27 @@ +{ + "copyright" : + { + "license" : "Apache-2.0", + "author_array" : + [ + { + "year" : "2023", + "name" : "Jayesh Badwaik", + "email" : "j.badwaik@fz-juelich.de" + } + ] + }, + "header_array" : [ ], + "typename" : "kaira::detail::char_kind", + "underlying_type" : "std::size_t", + "option_map" : + { + "unknown" : "0", + "letter" : "1", + "digit" : "2", + "identifier_symbol" : "3", + "nonidentifier_symbol" : "4", + "wschar" : "5" + }, + "default_option" : "unknown" +} diff --git a/src/jnum/kaira/detail/token_kind.jnum b/src/jnum/kaira/detail/token_kind.jnum new file mode 100644 index 0000000000000000000000000000000000000000..c2210b1666048399f03ea285e959009d9645dd18 --- /dev/null +++ b/src/jnum/kaira/detail/token_kind.jnum @@ -0,0 +1,26 @@ +{ + "copyright" : + { + "license" : "Apache-2.0", + "author_array" : + [ + { + "year" : "2023", + "name" : "Jayesh Badwaik", + "email" : "j.badwaik@fz-juelich.de" + } + ] + }, + "header_array" : [ ], + "typename" : "kaira::detail::token_kind", + "underlying_type" : "std::size_t", + "option_map" : + { + "unknown" : "0", + "key" : "1", + "identifier" : "2", + "nonidentifier" : "3", + "string_literal" : "4" + }, + "default_option" : "unknown" +} diff --git a/test/unit/cpp/CMakeLists.txt b/test/unit/cpp/CMakeLists.txt index bb1aceafbc5471f9461a8af9371aca52d6b36178..c6f2098fe973ecb6cb5b28d4741b5cb6aa670347 100644 --- a/test/unit/cpp/CMakeLists.txt +++ b/test/unit/cpp/CMakeLists.txt @@ -4,6 +4,7 @@ # -------------------------------------------------------------------------------------------------- add_unit_test_directory(bati libtestzell cpp "unit_test,production.test") +add_unit_test_directory(kaira libtestzell cpp "unit_test,production.test") add_unit_test_directory(mol libtestzell cpp "unit_test,production.test") add_unit_test_directory(noddy libtestzell cpp "unit_test,production.test") add_unit_test_directory(nola libtestzell cpp "unit_test,production.test") diff --git a/test/unit/cpp/kaira/detail.token.t.cpp b/test/unit/cpp/kaira/detail.token.t.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f63184e5dfdc97cc6f8b7610ce5814ad536db06 --- /dev/null +++ b/test/unit/cpp/kaira/detail.token.t.cpp @@ -0,0 +1,60 @@ +// ------------------------------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: (C) 2022 Jayesh Badwaik <j.badwaik@fz-juelich.de> +// ------------------------------------------------------------------------------------------------- + +#include <catch2/catch_test_macros.hpp> +#include <jnum/jnum.hpp> +#include <kaira/detail/token.hpp> +#include <testmol/compat/catch_main.hpp> + +#include <iostream> + +TESTMOL_CATCH_MAIN("test/unit/cpp/kaira/detail/token") + +TEST_CASE("Simple Test Case", "[all]") +{ + auto input_array = std::vector<std::string>{ + "tora-test", + "--test-dir", + "../build", + "--passthrough", + "--input ../testdata --output ../output", + "--preset", + "production.test", + "--source-dir", + "../code"}; + + auto token_array = kaira::detail::lex(input_array); + + REQUIRE(token_array.size() == 9); + + REQUIRE(token_array[0].value() == "tora-test"); + REQUIRE(token_array[0].kind() == kaira::detail::token_kind::identifier); + + REQUIRE(token_array[1].value() == "--test-dir"); + + REQUIRE(token_array[1].kind() == kaira::detail::token_kind::key); + + REQUIRE(token_array[2].value() == "../build"); + REQUIRE(token_array[2].kind() == kaira::detail::token_kind::nonidentifier); + + REQUIRE(token_array[3].value() == "--passthrough"); + REQUIRE(token_array[3].kind() == kaira::detail::token_kind::key); + + REQUIRE(token_array[4].value() == "--input ../testdata --output ../output"); + std::cout << jnum::to_string_view(token_array[4].kind()) << std::endl; + REQUIRE(token_array[4].kind() == kaira::detail::token_kind::string_literal); + + REQUIRE(token_array[5].value() == "--preset"); + REQUIRE(token_array[5].kind() == kaira::detail::token_kind::key); + + REQUIRE(token_array[6].value() == "production.test"); + REQUIRE(token_array[6].kind() == kaira::detail::token_kind::identifier); + + REQUIRE(token_array[7].value() == "--source-dir"); + REQUIRE(token_array[7].kind() == kaira::detail::token_kind::key); + + REQUIRE(token_array[8].value() == "../code"); + REQUIRE(token_array[8].kind() == kaira::detail::token_kind::nonidentifier); +}