From 7f089045bce33cf309f807d1cee97a8beb7bb859 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov Copyright © 2009 Code Synthesis Tools CC Permission is granted to copy, distribute and/or modify this document
+ Permission is granted to copy, distribute, and/or modify this document
under the terms of the
MIT License.
Copyright © 2009 Code Synthesis Tools CC Permission is granted to copy, distribute and/or modify this document
+ Permission is granted to copy, distribute, and/or modify this document
under the terms of the
MIT License.
Command Line Interface (CLI) definition language is a domain-specific
- language (DSL) that was designed for specifying command line interfaces
- of C++ programs. CLI defintions are translated to C++ classes using the
- CLI compiler. These classes implement parsing of the command line
- arguments and provide a convenient interface for accessing the
- extracted data.1 Introduction
Beyond this guide, you may also find the following sources of information useful:
@@ -225,7 +225,7 @@In this chapter we will examine how to define a very simple command
line interface in CLI, translate this interface to C++, and use the
- result in our application. The code presented in this chapter is based
+ result in an application. The code presented in this chapter is based
on the hello
example which can be found in the
examples/hello/
directory of the CLI distribution.
Our hello
application is going to print a greeting
line for each name supplied on the command line. It will also
- support a number of command line options that can be used to
- customize the greeting line. These options are: --greeting
- and --exclamations
. The --greeting
- option allows us to specify the greeting pharse instead of the
+ support two command line options, --greeting
+ and --exclamations
, that can be used to
+ customize the greeting line. The --greeting
+ option allows us to specify the greeting phrase instead of the
default "Hello"
. The --exclamations
- option is used to specify how many exclamations marks should
- be prined at the end of each greeting. We will also support
+ option is used to specify how many exclamation marks should
+ be printed at the end of each greeting. We will also support
the --help
option which triggers printing of the
usage information.
Now we can write a description of the above command line interface
- in the CLI language and save it into hello.cli
:
We can now write a description of the above command line interface
+ in the CLI language and save it into hello.cli
:
include <string>; @@ -261,12 +261,12 @@ class options clear (the CLI language is covered in greater detail in the next chapter), it should be easy to connect declarations inhello.cli
to the command line interface described in - the preceeding paragrpahs. The next step is to translate this + the preceding paragraphs. The next step is to translate this interface specification to C++. -2.2 Translating CLI Defintions to C++
+2.2 Translating CLI Definitions to C++
-Now we are ready to translate our
hello.cli
to C++. +Now we are ready to translate
@@ -277,8 +277,8 @@ $ cli hello.clihello.cli
to C++. To do this we invoke the CLI compiler from a terminal (UNIX) or a command prompt (Windows):This invocation of the CLI compiler produces three C++ files:
@@ -315,12 +315,12 @@ private: CLI class. For each option in this CLI class an accessor function is generated inside the C++ class. Thehello.hxx
hello.ixx
, and -hello.cxx
. You can change the extensions in these - files with the compiler command line options. See the +hello.cxx
. You can change the file name extensions + for these files with the compiler command line options. See the CLI Compiler Command Line Manual for more information.options
C++ class also defines a number of overloaded constructs that we can use to parse the -argc/argv
array. Let's now see how we can use this genearted +argc/argv
array. Let's now see how we can use this generated class to implement option parsing in ourhello
application.2.3 Implementing Application Logic
-At this point we have all the parts we need to implement our +
At this point we have everything we need to implement our application:
@@ -382,11 +382,11 @@ main (int argc, char* argv[])At the beginning of our application we create the
options
object which parses the command line. Theend
variable - contains the index of the first non-option argument. Then we access + contains the index of the first non-option argument. We then access the option values as needed during the application execution. We also - catch and print thecli::exception
exception in case - something goes wrong (for example, an unknown option is specified - or an option value is invalid). + catch and printcli::exception
in case something goes + wrong, for example, an unknown option is specified or an option value + is invalid.2.4 Compiling and Running
@@ -431,16 +431,16 @@ usage: driver <options> <names>3 CLI Language
This chapter describes the CLI language and its mapping to C++. - A CLI definition unit consists of zero or more Include - Directives followed by one or more Namespace Definition - or Option Class Definition. C and C++-style comments - can be used anywhere in the CLI definition unit except in character and + A CLI file consists of zero or more Include + Directives followed by one or more Namespace Definitions + or Option Class Definitions. C and C++-style comments + can be used anywhere in the CLI file except in character and string literals.
3.1 Option Class Definition
The central part of the CLI language is option class. An - option class contains one or more option definition, for + option class contains one or more option definitions, for example:
@@ -498,18 +498,18 @@ public:An option class is mapped to a C++ class with the same name. The - C++ class defines a set of public overloaded constructors, public - copy constructor and assignment operator, as well as a set of public + C++ class defines a set of public overloaded constructors, a public + copy constructor and an assignment operator, as well as a set of public accessor functions corresponding to option definitions.
The
argc/argv
arguments in the overloaded constructors are used to pass the command line arguments array, normally as passed - tomail()
. Thestart
argument is used to + tomain()
. Thestart
argument is used to specify the position in the arguments array from which the parsing - should start. Constructor that don't have this argument start from - position 1, skipping the executable name inargv[0]
. + should start. The constructors that don't have this argument, start + from position 1, skipping the executable name inargv[0]
. Theend
argument is used to return the position in - the arguments array where parsing of options stopped. This is the + the arguments array where the parsing of options stopped. This is the position of the first program argument, if any.The
opt_mode
andarg_mode
arguments @@ -540,10 +540,10 @@ namespace cliIf the mode is
skip
, the parser skips an unknown option or argument and continue parsing. If the mode isstop
, the parser stops the parsing process. The - position of the unknown entitiy is stored in theend
+ position of the unknown entity is stored in theend
argument. If the mode isfail
, the parser throws thecli::unknown_option
orcli::unknown_argument
- exception (described blow) on encounertin an unknown option or argument, + exception (described blow) on encountering an unknown option or argument, respectively.The parsing constructor (those with the
+ is specified for an option of typeargc/argv
arguments) @@ -554,11 +554,11 @@ namespace cli described above. Themissing_value
exception is thrown when an option value is missing. Theinvalid_value
exception is thrown when an option value is invalid, for example, a non-integer value - is speicified for an option of typeint
.int
.All CLI exceptions are derived from the common
@@ -655,21 +655,21 @@ namespace clicli::exception
- class which provides a polymorphicstd::ostream
insertion - support. For example, you can catch thecli::unknown_option
+ class which implements the polymorphicstd::ostream
insertion. + For example, if you catch thecli::unknown_option
exception ascli::exception
and print it tostd::cerr
, you will get the error message corresponding to theunknown_option
exception.3.2 Option Definition
An option definition consists of there components: type, - name, and default value. Option type can be any - C++ type as long as its string representation can be extracted using + name, and default value. An option type can be any + C++ type as long as its string representation can be parsed using the
-std::istream
interface. If the option type is - user-define then you will need to include its declaration using + user-defined then you will need to include its declaration using the Include Directive.An option of any type other that
bool
is expected to +An option of a type other than
bool
is expected to have a value. An option of typebool
is treated as a flag and does not have a value. That is, a mere presence of such - an option on the command line sets this option value to + an option on the command line sets this option's value totrue
.The name component specifies the option name as it will be entered - in the command line. A name can contain any number of aliases seperated - by
|
. The C++ acessor function name is derived from the + in the command line. A name can contain any number of aliases separated + by|
. The C++ accessor function name is derived from the first name by removing any leading special characters, such as-
,/
, etc., and replacing special characters in other places with underscore. For example, the following option @@ -693,7 +693,7 @@ class optionsWhile any option alias can be used on the command line to specify - this option value.
+ this option's value.If the option name conflicts with one of the CLI language keywords, it can be specified as a string literal:
@@ -706,7 +706,7 @@ class optionsThe final component of the option definition is the optional default - value. If the default value is not specified then the option is + value. If the default value is not specified, then the option is initialized with the default constructor. In particular, this means that a
@@ -732,8 +732,8 @@ class optionsbool
option will be initialized tofalse
, anint
option will be initialized to0
, etc.The assignment initialization supports character, string, boolean, and simple integer literals (including negative integers) as well - as identifiers. For more complex expression use the constructor - initialization or wrap the expression in parenthesis, for example:
+ as identifiers. For more complex expressions use the constructor + initialization or wrap the expressions in parenthesis, for example:include "constants.hxx"; // Defines default_value. @@ -746,17 +746,17 @@ class options };-By default when an option is specified two or more times on the command +
By default, when an option is specified two or more times on the command line, the last value overrides all the previous ones. However, a number of standard C++ containers are handled differently to allow collecting multiple option values or building key-value maps. These - containers are
std::vector
,std::set
and + containers arestd::vector
,std::set
, andstd::map
.When
@@ -801,21 +801,21 @@ class optionsstd::vector
orstd::set
is specified - as an option type, all values for this option are inserted into the + as an option type, all the values for this option are inserted into the container in the order they are encountered. As a result, -std::vector
will conatin all the values, inclduing +std::vector
will contain all the values, including duplicates whilestd::set
will contain all the unique values. For example:If you are using user-defined types in your option definitions, you will need to include their declarations with the include - directive. Include directives can specify
< >
or + directive. Include directives can use< >
or" "
-enclosed paths. The CLI compiler does not - actully open or read these files. Instead the include directives - are translated to C++ preprocessor#include
directive + actually open or read these files. Instead, the include directives + are translated to C++ preprocessor#include
directives in the generated C++ header file. For example, the following CLI definition:include <string>; -include "types.hxx"; // Defines the name class. +include "types.hxx"; // Defines the name_type class. class options { std::string --string; - name --name; + name_type --name; };@@ -832,7 +832,7 @@ class options const std::string& string () const; - const name& + const name_type& name () const; ... @@ -840,8 +840,8 @@ class options
Without the #include
directives the std::string
- and name
type in the options
class would be
- undeclared and result in compillation errors.
name_type
types in the options
class would
+ be undeclared and result in compilation errors.
The above CLI namespace strcture would result in the equivalent C++ - namespaces strcture:
+The above CLI namespace structure would result in the equivalent C++ + namespaces structure:
namespace compiler -- cgit v1.1