Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/Control/Keyword.hpp 4 : : \copyright 2012-2015 J. Bakosi, 5 : : 2016-2018 Los Alamos National Security, LLC., 6 : : 2019-2021 Triad National Security, LLC. 7 : : All rights reserved. See the LICENSE file for details. 8 : : \brief Generic definition of a keyword 9 : : \details Generic definition of all keywords - both command-line arguments 10 : : and control file keywords. 11 : : */ 12 : : // ***************************************************************************** 13 : : #ifndef Keyword_h 14 : : #define Keyword_h 15 : : 16 : : #include <optional> 17 : : 18 : : #include "NoWarning/set.hpp" 19 : : #include "NoWarning/pegtl.hpp" 20 : : 21 : : #include "Has.hpp" 22 : : #include "Escaper.hpp" 23 : : 24 : : namespace tk { 25 : : 26 : : //! Helper to declare a set of command line keywords 27 : : //! \details This ensures that a compile-error is generated if there is no alias 28 : : //! defined for the keyword, and also if the aliases are non-unique. 29 : : template< typename... T > 30 : : class cmd_keywords { 31 : : public: 32 : : using set = brigand::set< T... >; 33 : : private: 34 : : template< typename K > using alias = typename K::info::alias::type; 35 : : using aliases = brigand::set< alias<T>... >; 36 : : }; 37 : : 38 : : } // tk:: 39 : : 40 : : namespace kw { 41 : : 42 : : using namespace tao; 43 : : 44 : : //! \brief Keyword alias helper 45 : : //! \details This struct is used to define both a type and a value for a keyword 46 : : //! alias, which is a single character. Used for command-line arguments, e.g., 47 : : //! --help, -h, where 'h' is the alias for keyword 'help'. 48 : : //! \see Control/Keywords.h 49 : : template< int Char > 50 : : struct Alias { 51 : : using type = pegtl::one< Char >; 52 : : static const int value = Char; 53 : : }; 54 : : 55 : : //! \brief Generic definition of a keyword 56 : : //! \details A keyword is a struct that collects the information that makes up a 57 : : //! keyword. The requirement on the first template argument, Info, is that it 58 : : //! must define the name(), shortDescription(,) and longDescription() member 59 : : //! functions returning compile-time (static) std::strings. The 60 : : //! shortDescription() member function is used to return a short description 61 : : //! of what the keyword is used for, while the longDescription() member 62 : : //! function is used for a longer, e.g., a paragraph-long, description on 63 : : //! what the keyword can be used for and how it can and should be used. The 64 : : //! last template parameter is a pegtl string, a list of character constants, 65 : : //! specifying the case-sensitive characters that make up the keyword, which 66 : : //! is then matched by the parser. The keyword must be at least one character 67 : : //! long, but otherwise its length is only limited by the compiler's 68 : : //! recursion handling capability of variadic templates. While the name(), 69 : : //! shortDescription() and longDescription() member functions of Info are 70 : : //! required, there are also optional ones, such as 71 : : //! Info::exptect::description(), which, if defined, must also be static and 72 : : //! must return a std::string, describing the type the particular keyword 73 : : //! expects during parsing. This is optional since not every keyword expects 74 : : //! a value (or values) of a particular type. For example, the keyword 'end' 75 : : //! is simply used to close a block in the input file, and what follows does 76 : : //! not have a relationship to the keyword. A counterexample is is 'title', 77 : : //! which expects a double-quoted string immediately after the keyword 78 : : //! title'. 79 : : //! \see For example client-code and more detailed documentation on the possible 80 : : //! fields, see Control/Keywords.h. 81 : : template< typename Info, typename > struct keyword; 82 : : template< typename Info, char... Chars > 83 : : struct keyword< Info, pegtl::string< Chars... > > { 84 : : 85 : : //! Accessor to keyword as pegtl::string 86 : : using pegtl_string = pegtl::string< Chars... >; 87 : : 88 : : //! Accessor to keyword as std::string 89 : : //! \return Keyword as std::string 90 : 60437 : static std::string string() { return kw::escaper< Chars... >::result(); } 91 : : 92 : : //! Accessor to required short name of a keyword 93 : : //! \return Name of keyword as std::string 94 : : static std::string name() { return Info::name(); } 95 : : 96 : : //! Accessor to required short description of a keyword 97 : : //! \return Short help as std::string 98 : 60437 : static std::string shortDescription() { return Info::shortDescription(); } 99 : : 100 : : //! Accessor to required long description of a keyword 101 : : //! \return Long help as std::string 102 : 60437 : static std::string longDescription() { return Info::longDescription(); } 103 : : 104 : : //! Bring template argument 'Info' to scope as 'info' 105 : : //! \details This is used to access, e.g., Info::alias, etc., if exist. 106 : : //! \see tk::grm::alias 107 : : //! \see tk::grm::readcmd 108 : : using info = Info; 109 : : 110 : : //! Alias accessor for keyword 111 : : //! \return An initialized (or uninitialized) std::optional< std::string > 112 : : //! \details Though an alias is only a single character, it returns it as 113 : : //! std::string since pegtl::string returns std::string. 114 : : template< typename T = Info > 115 : 62458 : static std::optional< std::string > alias() { 116 : : if constexpr( tk::HasTypedef_alias_v< T > ) 117 [ + - ][ + - ]: 62458 : return std::string( 1, static_cast<char>( Info::alias::value ) ); 118 : : else 119 : : return std::nullopt; 120 : : } 121 : : 122 : : //! Expected type description accessor for keyword 123 : : //! \return An initialized (or uninitialized) std::optional< std::string > 124 : : template< typename T = Info > 125 : 60437 : static std::optional< std::string > expt() { 126 : : if constexpr( tk::HasFunction_expect_description_v< T > ) 127 [ + - ]: 28745 : return Info::expect::description(); 128 : : else 129 : 31692 : return std::nullopt; 130 : : } 131 : : 132 : : //! Expected choices description accessor for a keyword 133 : : //! \return An initialized (or uninitialized) std::optional< std::string > 134 : : template< typename T = Info > 135 : 60437 : static std::optional< std::string > choices() { 136 : : if constexpr( tk::HasFunction_expect_choices_v< T > ) 137 [ + - ]: 8565 : return Info::expect::choices(); 138 : : else 139 : 51872 : return std::nullopt; 140 : : } 141 : : 142 : : //! Expected lower bound accessor for a keyword 143 : : //! \return An initialized (or uninitialized) std::optional< std::string > 144 : : template< typename T = Info > 145 : 60437 : static std::optional< std::string > lower() { 146 : : if constexpr( tk::HasVar_expect_lower_v< T > ) 147 [ + - ]: 8565 : return std::to_string( Info::expect::lower ); 148 : : else 149 : 51872 : return std::nullopt; 150 : : } 151 : : 152 : : //! Expected upper bound accessor for a keyword 153 : : //! \return An initialized (or uninitialized) std::optional< std::string > 154 : : template< typename T = Info > 155 : 60437 : static std::optional< std::string > upper() { 156 : : if constexpr( tk::HasVar_expect_upper_v< T > ) 157 [ + - ]: 8565 : return std::to_string( Info::expect::upper ); 158 : : else 159 : 51872 : return std::nullopt; 160 : : } 161 : : }; 162 : : 163 : : } // kw:: 164 : : 165 : : #endif // Keyword_h