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 : : //! Helper to ensure uniqueness of policy codes for keywords 39 : : //! \details This ensures that a compile-error is generated if the policy codes 40 : : //! of the keywords passed in as T... are not unique. 41 : : template< typename... T > 42 : : class unique_codes { 43 : : public: 44 : : using list = brigand::list< T... >; 45 : : private: 46 : : template< typename K > using code = typename K::info::code::type; 47 : : using set = brigand::set< code<T>... >; 48 : : }; 49 : : 50 : : } // tk:: 51 : : 52 : : namespace kw { 53 : : 54 : : using namespace tao; 55 : : 56 : : //! \brief Keyword alias helper 57 : : //! \details This struct is used to define both a type and a value for a keyword 58 : : //! alias, which is a single character. Used for command-line arguments, e.g., 59 : : //! --help, -h, where 'h' is the alias for keyword 'help'. 60 : : //! \see Control/Keywords.h 61 : : template< int Char > 62 : : struct Alias { 63 : : using type = pegtl::one< Char >; 64 : : static const int value = Char; 65 : : }; 66 : : 67 : : //! \brief Keyword code helper 68 : : //! \details This struct is used to define both a type and a value for a keyword 69 : : //! code, which is a single character. Used for printing out policy code. 70 : : //! \see Control/Keywords.h 71 : : template< int Char > 72 : : struct Code { 73 : : using type = pegtl::one< Char >; 74 : : static const int value = Char; 75 : : }; 76 : : 77 : : //! \brief Generic definition of a keyword 78 : : //! \details A keyword is a struct that collects the information that makes up a 79 : : //! keyword. The requirement on the first template argument, Info, is that it 80 : : //! must define the name(), shortDescription(,) and longDescription() member 81 : : //! functions returning compile-time (static) std::strings. The 82 : : //! shortDescription() member function is used to return a short description 83 : : //! of what the keyword is used for, while the longDescription() member 84 : : //! function is used for a longer, e.g., a paragraph-long, description on 85 : : //! what the keyword can be used for and how it can and should be used. The 86 : : //! last template parameter is a pegtl string, a list of character constants, 87 : : //! specifying the case-sensitive characters that make up the keyword, which 88 : : //! is then matched by the parser. The keyword must be at least one character 89 : : //! long, but otherwise its length is only limited by the compiler's 90 : : //! recursion handling capability of variadic templates. While the name(), 91 : : //! shortDescription() and longDescription() member functions of Info are 92 : : //! required, there are also optional ones, such as 93 : : //! Info::exptect::description(), which, if defined, must also be static and 94 : : //! must return a std::string, describing the type the particular keyword 95 : : //! expects during parsing. This is optional since not every keyword expects 96 : : //! a value (or values) of a particular type. For example, the keyword 'end' 97 : : //! is simply used to close a block in the input file, and what follows does 98 : : //! not have a relationship to the keyword. A counterexample is is 'title', 99 : : //! which expects a double-quoted string immediately after the keyword 100 : : //! title'. 101 : : //! \see For example client-code and more detailed documentation on the possible 102 : : //! fields, see Control/Keywords.h. 103 : : template< typename Info, typename > struct keyword; 104 : : template< typename Info, char... Chars > 105 : : struct keyword< Info, pegtl::string< Chars... > > { 106 : : 107 : : //! Accessor to keyword as pegtl::string 108 : : using pegtl_string = pegtl::string< Chars... >; 109 : : 110 : : //! Accessor to keyword as std::string 111 : : //! \return Keyword as std::string 112 : 652555 : static std::string string() { return kw::escaper< Chars... >::result(); } 113 : : 114 : : //! Accessor to required short name of a keyword 115 : : //! \return Name of keyword as std::string 116 : 364964 : static std::string name() { return Info::name(); } 117 : : 118 : : //! Accessor to required short description of a keyword 119 : : //! \return Short help as std::string 120 : 138831 : static std::string shortDescription() { return Info::shortDescription(); } 121 : : 122 : : //! Accessor to required long description of a keyword 123 : : //! \return Long help as std::string 124 : 138831 : static std::string longDescription() { return Info::longDescription(); } 125 : : 126 : : //! Bring template argument 'Info' to scope as 'info' 127 : : //! \details This is used to access, e.g., Info::alias, etc., if exist. 128 : : //! \see tk::grm::alias 129 : : //! \see tk::grm::readcmd 130 : : using info = Info; 131 : : 132 : : //! Alias accessor for keyword 133 : : //! \return An initialized (or uninitialized) std::optional< std::string > 134 : : //! \details Though an alias is only a single character, it returns it as 135 : : //! std::string since pegtl::string returns std::string. 136 : : template< typename T = Info > 137 : 139418 : static std::optional< std::string > alias() { 138 : : if constexpr( tk::HasTypedef_alias_v< T > ) 139 [ + - ][ + - ]: 67554 : return std::string( 1, static_cast<char>( Info::alias::value ) ); 140 : : else 141 : 116900 : return std::nullopt; 142 : : } 143 : : 144 : : //! Policy code accessor for keyword 145 : : //! \return An initialized (or uninitialized) std::optional< std::string > 146 : : template< typename T = Info > 147 : 6982 : static std::optional< std::string > code() { 148 : : if constexpr( tk::HasTypedef_code_v< T > ) 149 [ + - ][ + - ]: 20946 : return std::string( 1, Info::code::value ); 150 : : else 151 : : return std::nullopt; 152 : : } 153 : : 154 : : //! Expected type description accessor for keyword 155 : : //! \return An initialized (or uninitialized) std::optional< std::string > 156 : : template< typename T = Info > 157 : 138831 : static std::optional< std::string > expt() { 158 : : if constexpr( tk::HasFunction_expect_description_v< T > ) 159 [ + - ]: 111094 : return Info::expect::description(); 160 : : else 161 : 83284 : return std::nullopt; 162 : : } 163 : : 164 : : //! Expected choices description accessor for a keyword 165 : : //! \return An initialized (or uninitialized) std::optional< std::string > 166 : : template< typename T = Info > 167 : 138831 : static std::optional< std::string > choices() { 168 : : if constexpr( tk::HasFunction_expect_choices_v< T > ) 169 [ + - ]: 25508 : return Info::expect::choices(); 170 : : else 171 : 126077 : return std::nullopt; 172 : : } 173 : : 174 : : //! Expected lower bound accessor for a keyword 175 : : //! \return An initialized (or uninitialized) std::optional< std::string > 176 : : template< typename T = Info > 177 : 138831 : static std::optional< std::string > lower() { 178 : : if constexpr( tk::HasVar_expect_lower_v< T > ) 179 [ + - ]: 19836 : return std::to_string( Info::expect::lower ); 180 : : else 181 : 128913 : return std::nullopt; 182 : : } 183 : : 184 : : //! Expected upper bound accessor for a keyword 185 : : //! \return An initialized (or uninitialized) std::optional< std::string > 186 : : template< typename T = Info > 187 : 138831 : static std::optional< std::string > upper() { 188 : : if constexpr( tk::HasVar_expect_upper_v< T > ) 189 [ + - ]: 4116 : return std::to_string( Info::expect::upper ); 190 : : else 191 : 136773 : return std::nullopt; 192 : : } 193 : : }; 194 : : 195 : : } // kw:: 196 : : 197 : : #endif // Keyword_h