1[/============================================================================== 2 Copyright (C) 2001-2011 Joel de Guzman 3 Copyright (C) 2001-2011 Hartmut Kaiser 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7===============================================================================/] 8 9[section Warming up] 10 11Learning how to use __karma__ is really simple. We will start from trivial 12examples, ramping up as we go. 13 14 15[heading Trivial Example #1 Generating a number] 16 17Let's create a generator that will output a floating-point number: 18 19 double_ 20 21Easy huh? The above code actually instantiates a Spirit floating point 22generator (a built-in generator). Spirit has many pre-defined generators and 23consistent naming conventions will help you finding your way through the maze. 24Especially important to note is that things related to identical entities (as 25in this case, floating point numbers) are named identically in __karma__ and in 26__qi__. Actually, both libraries are using the very same variable instance to 27refer to a floating point generator or parser: `double_`. 28 29 30[heading Trivial Example #2 Generating two numbers] 31 32Now, let's create a generator that will output a line consisting of two 33floating-point numbers. 34 35 double_ << double_ 36 37Here you see the familiar floating-point numeric generator `double_` used twice, 38once for each number. If you are used to see the `'>>'` operator for concatenating 39two parsers in __qi__ you might wonder, what's that `'<<'` operator doing in 40there? We decided to distinguish generating and parsing of sequences the same 41way as the std::stream libraries do: we use operator `'>>'` for input (parsing), 42and operator `'<<'` for output (generating). Other than that there is no 43significant difference. The above program creates a generator from two simpler 44generators, glueing them together with the sequence operator. The result is a 45generator that is a composition of smaller generators. Whitespace between 46numbers can implicitly be inserted depending on how the generator is invoked 47(see below). 48 49[note When we combine generators, we end up with a "bigger" generator, but 50 it's still a generator. Generators can get bigger and bigger, nesting more 51 and more, but whenever you glue two generators together, you end up with one 52 bigger generator. This is an important concept. 53] 54 55 56[heading Trivial Example #3 Generating one or more numbers] 57 58Now, creating output for two numbers is not too interesting. Let's create a 59generator that will output zero or more floating-point numbers in a row. 60 61 *double_ 62 63This is like a regular-expression Kleene Star. We moved the `*` to the front for 64the same reasons we did in __qi__: we must work with the syntax rules of C++. 65But if you know regular expressions (and for sure you remember those C++ syntax 66rules) it will start to look very familiar in a matter of a very short time. 67 68Any expression that evaluates to a generator may be used with the Kleene Star. 69Keep in mind, though, that due to C++ operator precedence rules you may need 70to put the expression in parentheses for complex expressions. As above, 71whitespace can be inserted implicitly in between the generated numbers, if 72needed. 73 74 75[heading Trivial Example #4 Generating a comma-delimited list of numbers] 76 77We follow the lead of __qi__'s warming up section and will create a generator 78that produces a comma-delimited list of numbers. 79 80 double_ << *(lit(',') << double_) 81 82Notice `lit(',')`. It is a literal character generator that simply generates 83the comma `','`. In this case, the Kleene Star is modifying a more complex 84generator, namely, the one generated by the expression: 85 86 (lit(',') << double_) 87 88Note that this is a case where the parentheses are necessary. The Kleene Star 89encloses the complete expression above, repeating the whole pattern in the 90generated output zero or more times. 91 92[heading Let's Generate!] 93 94We're done with defining the generator. All that's left is to invoke the 95generator to do its work. For now, we will use the `generate_delimited` function. 96One overload of this function accepts four arguments: 97 98# An output iterator accepting the generated characters 99# The generator expression 100# Another generator called the delimiting generator 101# The data to format and output 102 103While comparing this minimal example with an equivalent parser example we 104notice a significant difference. It is possible (and actually, it makes a lot 105of sense) to use a parser without creating any internal representation of the 106parsed input (i.e. without 'producing' any data from the parsed input). Using 107a parser in this mode checks the provided input against 108the given parser expression allowing to verify whether the input is parsable. 109For generators this mode doesn't make any sense. What is output generation 110without generating any output? So we always will have to supply the data the 111output should be generated from. In our example we supply a list of `double` 112numbers as the last parameter to the function `generate_delimited` (see code 113below). 114 115In this example, we wish to delimit the generated numbers by spaces. Another 116generator named `space` is included in Spirit's repertoire of predefined 117generators. It is a very trivial generator that simply produces spaces. It is 118the equivalent to writing `lit(' ')`, or simply `' '`. It has been 119implemented for similarity with the corresponding predefined `space` parser. 120We will use `space` as our delimiter. The delimiter is the one responsible for 121inserting characters in between generator elements such as the `double_` and 122`lit`. 123 124Ok, so now let's generate (for the complete source code of this example please 125refer to [@../../example/karma/num_list1.cpp num_list1.cpp]). 126 127[import ../../example/karma/num_list1.cpp] 128[tutorial_karma_numlist1] 129 130[note You might wonder how a `vector<double>`, which is actually a single data 131 structure, can be used as an argument (we call it attribute) to a sequence 132 of generators. This seems to be counter intuitive and doesn't match with 133 your experience of using `printf`, where each formatting placeholder has 134 to be matched with a corresponding argument. Well, we will explain this 135 behavior in more detail later in this tutorial. For now just consider 136 this to be a special case, implemented on purpose to allow more flexible 137 output formatting of STL containers: sequences accept a single container 138 attribute if all elements of this sequence accept attributes compatible 139 with the elements held by this container.] 140 141The generate function returns `true` or `false` depending on the result of the 142output generation. As outlined in different places of this documentation, a 143generator may fail for different reasons. One of the possible reasons is an 144error in the underlying output iterator (memory exhausted or disk full, etc.). 145Another reason might be that the data doesn't match the requirements of a 146particular generator. 147 148[note `char` and `wchar_t` operands 149 150 The careful reader may notice that the generator expression has `','` instead 151 of `lit(',')` as the previous examples did. This is ok due to C++ syntax 152 rules of conversion. Spirit provides `<<` operators that are overloaded to 153 accept a `char` or `wchar_t` argument on its left or right (but not both). 154 An operator may be overloaded if at least one of its parameters is a 155 user-defined type. In this case, the `double_` is the 2nd argument to 156 `operator<<`, and so the proper overload of `<<` is used, converting `','` 157 into a character literal generator. 158 159 The problem with omitting the `lit` should be obvious: `'a' << 'b'` is not a 160 spirit generator, it is a numeric expression, left-shifting the ASCII (or 161 another encoding) value of `'a'` by the ASCII value of `'b'`. However, both 162 `lit('a') << 'b'` and `'a' << lit('b')` are Spirit sequence generators 163 for the letter `'a'` followed by `'b'`. You'll get used to it, sooner or 164 later. 165] 166 167Note that we inlined the generator directly in the call to `generate_delimited`. 168Upon calling this function, the expression evaluates into a temporary, 169unnamed generator which is passed into the `generate_delimited` function, 170used, and then destroyed. 171 172Here, we chose to make the generate function generic by making it a template, 173parameterized by the output iterator type. By doing so, it can put the generated 174data into any STL conforming output iterator. 175 176[endsect] [/ Warming up] 177