src/Control/Keywords.h file

Definition of all keywords.

This file contains the definition of all keywords, including those of command-line argument parsers as well as input, i.e., control, file parsers. All keywords are shared among all parsers of all executables.

All keywords are case-sensitive.

The information contained in this file is used to build data structures for on-screen help on the command-line arguments and control file keywords, available via the –help, –helpctr, and –helpkw command-line arguments.

A note on design: Defining structs that have static member functions returning a std::string is a way of storing C++-style strings at compile-time (which is not possible in a straightforward manner at this time). This could also be done with C-style const char* as well. The '*_info' structs store these strings, which then is used to specialize the kw::keyword template, defined in Control/Keyword.h. Specializing the keyword template also requires a specification of the precise string of characters that make up a keyword eventually matched by the parsers. Since these are all template arguments, the construction of keywords, their help, as well as all grammars, are entirely assembled at compile-time. Since the '*_info' struct member functions are static, they can be called without instantiating an object and thus available at compile-time.

The definition of an '*_info' struct requires at least the name, short, and long descriptions, defined by member functions name(), shortDescription(), and longDescription(), respectively. Everything else is optional. However, when adding a new keyword it is highly recommended to define all of the optional members if they make sense for the given keyword. If an expect value type is also given, that can be hooked up into where it is used.

The most general definition of a keyword is as follows:

// Keyword info definition
struct keyword_info {

  // Required very short name, usually a single word or (for e.g.
  // policies) a single character. This can be the keyword itself, but
  // does not have to be. This field is used as an id of the option or
  // setting.
  static std::string name() { return "Name"; }

  // Required short keyword description
  static std::string shortDescription() { return "Short description"; }

  // Required detailed keyword description. This returns a string literal,
  // since this is usually multi-line and it is less work to maintain this
  // way.
  static std::string longDescription() { return
    R"(Longer, possibly multi-line description of the keyword. Example
    usage of the keyword is welcome here. Don't worry about formatting:
    when this field is printed, extra spaces will be removed and line
    breaks will be inserted.)";
  }

  // Optional keyword alias. See also kw::Alias and
  // <tpl_install_dir>/include/pegtl/pegtl/constants.hh for examples
  // of what can be passed as template arguments (basically single
  // characters). The one below defines the character 'c' as the alias.
  // Aliases are single character long. The idea of an alias is to have a
  // long as well as a short keyword for the same functionality.
  // Currently, this is only hooked up for command-line arguments and not
  // for control-file keywords, which is intentional. Command-line
  // arguments are a lot less than control file keywords and are more
  // frequently typed by the user. Thus command-line argument aliases are
  // user-friendly. There are many control file keywords and aliases would
  // only cause confusion. Defining an alias for a command-line argument
  // enables the command-line parser to match on '--longer_keyword' as
  // well as on '-c'. Depending on whether the alias typedef is defined
  // for a keyword or not, the correct grammar is automatically generated
  // at compile-time, matching on both the longer keyword as well as on
  // the alias. Defining an alias for a control file keyword can be done
  // but has no effect in a control file parser.
  using alias = Alias< c >;

  // Optional single-character (policy) code. See also kw::Code and
  // <tpl_install_dir/include/pegtl/pegtl/constants.hh for examples
  // of what can be passed as template arguments (basically single
  // characters). The one below defines the character 'C' as the (policy)
  // code. This code is used for abbreviating policies used to configure
  // various orthogonal behaviors of classes using policy-based design.
  using code = Code< C >;

  // Optional expected data for the keyword - bundled to struct expect.
  // This struct is entirely optional within a keyword definition.
  // However, if it is defined, it must at least define the static member
  // function description() which returns the description of the type the
  // keyword expects. It may also optionally define the following fields:
  //
  //    - type - defining the expected type
  //    - lower - lower bound of the expected value
  //    - upper - upper bound of the expected value
  //    - choices - valid choices for the expected value
  //
  struct expect {

    // If this struct is defined, required expected type description, max
    // 10 characters long
    static std::string description() { return "int"; }

    // Optional expected type
    using type = std::streamsize;

    // Optional expected value lower bound
    static const type lower = 1;

    // Optional expected value upper bound
    static const type upper =
      std::numeric_limits< tk::real >::digits10 + 1;

    // Optional expected valid choices description, here giving
    // information on the expected type and the valid bounds. Note that
    // this can be any string, but if they exist, it is a good idea give
    // at least some information on the bounds, as below, since the bounds
    // are NOT displayed in the help for a keyword. This decision keeps
    // the bounds specifications generic since they can be any type. As a
    // result, the help structures, defined in HelpFactory.h, are simpler
    // as they do not have to be parameterized by the type of the bounds,
    // which greatly simplifies that code.
    static std::string choices() {
      return "integer [" + std::to_string(lower) + "..." +
             std::to_string(upper) + ']';
    }

  };

};

// Keyword definition, passing the above info struct as the first
// template argument, and the rest of the template arguments are the
// characters of the keyword to be matched by the parser. Remember: all
// keywords are case-sensitive. This one contrived example below defines
// keyword 'kw', matching the keyword 'KeYwOrD'.
using kw = keyword< keyword_info, K,e,Y,w,O,r,D >;