getting_started.qbk 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205
  1. [#getting_started]
  2. [section Getting started with Boost.Metaparse]
  3. [section 1. Introduction]
  4. This tutorial shows you how to build a parser for a small calculator language
  5. from the ground up. The goal is not to have a complete calculator, but to show
  6. you the most common situations one can face while building a parser using
  7. Metaparse. This tutorial assumes, that you have some template metaprogramming
  8. experience.
  9. [section 1.1. Testing environment]
  10. While you are using Metaparse, you will be writing parsers turning an input text
  11. into a type. These types can later be processed by further template
  12. metaprograms. While you are working on your parsers, you'll probably want to
  13. look at the result of parsing a test input. This tutorial assumes that you can
  14. use [@http://metashell.org Metashell]. Since the
  15. [@http://metashell.org/about/demo online demo] makes the Boost
  16. headers available, you can use that in the tutorial as well.
  17. If you install Metashell on your computer, make sure that you have the Boost
  18. libraries and the `getting_started` example of Metaparse on the include path.
  19. For example, you can start Metashell with the following arguments:
  20. $ metashell -I$BOOST_ROOT -I$BOOST_ROOT/libs/metaparse/example/getting_started
  21. `$BOOST_ROOT` refers to the ['boost root directory] (where you have checked
  22. out the Boost source code).
  23. This tutorial is long and therefore you might want to make shorter or longer
  24. breaks while reading it. To make it easy for you to stop at a certain point and
  25. continue later (or to start in the middle if you are already familiar with the
  26. basics) Metaparse has a `getting_started` directory in the `example`s. This
  27. contains the definitions for each section of this tutorial.
  28. If you're about to start (or continue) this guide from section 5.2.1, you can
  29. include `5_2_1.hpp`. This will define everything you need to start with that
  30. section.
  31. [note
  32. You have access to these headers in the online Metashell demo as well. For
  33. example you can include the `<boost/metaparse/getting_started/5_2_1.hpp>`
  34. header to start from section 5.2.1.
  35. ]
  36. [endsect]
  37. [section 1.2. Using a "regular" testing environment]
  38. If you have no access to Metashell or you prefer using your regular C++
  39. development environment while processing this tutorial, this is also possible.
  40. The tutorial (and usually experimenting with Metaparse) requires that you
  41. evaluate different template metaprogramming expressions and check their result,
  42. which is a type. Thus, to try the examples of this tutorial you need a way to
  43. be able to display the result of evaluating a template metaprogram. This section
  44. shows you two options.
  45. [section 1.2.1. Enforcing an error message or a warning containing the result of
  46. the metafunction call]
  47. You can either use `boost::mpl::print` or `mpllibs::metamonad::fail_with_type`
  48. to enforce a warning or an error message containing the result of a metaprogram
  49. evaluation. For example to see what
  50. [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`]`("11 + 2")` refers to,
  51. you can create a `test.cpp` with the following content:
  52. #include <boost/metaparse/string.hpp>
  53. #include <boost/mpl/print.hpp>
  54. boost::mpl::print<BOOST_METAPARSE_STRING("11 + 2")> x;
  55. If you try to compile it, the compiler will display warnings containing the
  56. type the expression
  57. [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`]`("11 + 2")` constructs.
  58. To use this technique for this tutorial, you need to add all the includes and
  59. definitions the tutorial suggests typing in the shell to your `test.cpp` file.
  60. When the shell suggests to try to call some metafunction (or you'd like to try
  61. something out), you need to replace the template argument of `boost::mpl::print`
  62. with the expression in question and recompile the code.
  63. [endsect]
  64. [section 1.2.2. Displaying the result of the metafunction call at runtime]
  65. You can also display the result of metaprograms at runtime. You can use the
  66. [@http://boost.org/libs/type_index Boost.TypeIndex] library to do this. For
  67. example to see what
  68. [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`]`("11 + 2")` refers to,
  69. you can create a `test.cpp` with the following content:
  70. #include <boost/metaparse/string.hpp>
  71. #include <boost/type_index.hpp>
  72. #include <iostream>
  73. int main()
  74. {
  75. std::cout
  76. << boost::typeindex::type_id_with_cvr<BOOST_METAPARSE_STRING("11 + 2")>()
  77. << std::endl;
  78. }
  79. If you compile and run this code, it will display the type on the standard
  80. output.
  81. [endsect]
  82. [endsect]
  83. [endsect]
  84. [section 2. The text to parse]
  85. With Metaparse you can create template metaprograms parsing an input text. To
  86. pass the input text to the metaprograms, you need to represent them as types.
  87. For example let's represent the text `"Hello world"` as a type. The most
  88. straightforward way of doing it would be creating a variadic template class
  89. taking the characters of the text as template arguments:
  90. template <char... Cs>
  91. struct string;
  92. The text `"11 + 2"` can be represented the following way:
  93. string<'1', '1', ' ', '+', ' ', '2'>
  94. Metaparse provides this type for you. Run the following command in Metashell:
  95. > #include <boost/metaparse/string.hpp>
  96. [note
  97. Note that the `>` character at the beginning of the above code example is the
  98. prompt of Metashell. It is added to the code examples as a hint to what you
  99. should run in Metashell (or add to your test `cpp` file if you are using a
  100. regular development environment).
  101. ]
  102. [note
  103. Note that in the [@http://abel.web.elte.hu/shell/metashell.html online-demo]
  104. of Metashell you can paste code into the shell by right-clicking on the shell
  105. somewhere and choosing ['Paste from browser] in the context menu.
  106. ]
  107. This will make this type available for you. Now you can try running the
  108. following command:
  109. > boost::metaparse::string<'1', '1', ' ', '+', ' ', '2'>
  110. The shell will echo (almost) the same type back to you. The only difference is
  111. that it is in a sub-namespace indicating the version of Metaparse being used.
  112. The nice thing about this representation is that metaprograms can easily access
  113. the individual characters of the text. The not so nice thing about this
  114. representation is that if you want to write the text `"Hello world"` in your
  115. source code, you have to type a lot.
  116. Metaparse provides a macro that can turn a string literal into an instance of
  117. [link string `boost::metaparse::string`]. This is the
  118. [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`] macro. You get it by
  119. including `<boost/metaparse/string.hpp>`. Let's try it by running the following
  120. command in Metashell:
  121. > BOOST_METAPARSE_STRING("11 + 2")
  122. You will get the same result as you got by instantiating
  123. [link string `boost::metaparse::string`] yourself.
  124. [endsect]
  125. [section 3. Creating a simple parser]
  126. [note Note that you can find everything that has been included and defined so far [link before_3 here].]
  127. Let's try creating a parser. We will start with creating a parser for something
  128. simple: we will be parsing integer numbers, such as the text `"13"`. You can
  129. think of this first parsing exercise as a ['template metaprogramming
  130. string-to-int conversion] because we expect to get the value `13` as the result
  131. of parsing.
  132. [note
  133. You know the difference between `"13"` and `13` in C++. One of them is a
  134. character array, the other one is an integral value. But what is the
  135. difference between them in template metaprogramming? They are represented by
  136. different types. For example `"13"` is represented by
  137. [link string `string`]`<'1', '3'>` while `13` is represented by
  138. `std::integral_constant<int, 13>`.
  139. ]
  140. To build a parser, we need to specify the grammar to use. Metaparse provides
  141. building blocks (called parsers) we can use to do this and one of them is the
  142. [link int_ `int_`] parser which does exactly what we need: it parses integers.
  143. To make it available, we need to include it:
  144. > #include <boost/metaparse/int_.hpp>
  145. Our grammar is simple: [link int_ `int_`]. (Don't worry, we'll parse more
  146. complicated languages later).
  147. A parser is a [link metafunction_class template metafunction class]. It can be
  148. used directly, but its interface is designed for completeness and not for ease
  149. of use. Metaparse provides the [link build_parser `build_parser`]
  150. [link metafunction metafunction] that adds a wrapper to parsers with a simple
  151. interface.
  152. [note
  153. In this tutorial, we will always be wrapping our parsers with this. We will
  154. call these wrapped parsers parsers as well. If you are interested in it, you
  155. can learn about the complete interface of parsers [link parser here].
  156. ]
  157. Let's create a parser using [link int_ `int_`] and
  158. [link build_parser `build_parser`]:
  159. > #include <boost/metaparse/build_parser.hpp>
  160. > using namespace boost::metaparse;
  161. > using exp_parser1 = build_parser<int_>;
  162. [link getting_started_0 copy-paste friendly version]
  163. First we need to include `build_parser.hpp` to make
  164. [link build_parser `build_parser`] available. Then we make our lives easier by
  165. running `using namespace boost::metaparse;`. The third command defines the
  166. parser: we need to instantiate the [link build_parser `build_parser`] template
  167. class with our parser ([link int_ `int_`] in this case) as argument.
  168. Now that we have a parser, let's parse some text with it (if you haven't done it
  169. yet, include `boost/metaparse/string.hpp`):
  170. > exp_parser1::apply<BOOST_METAPARSE_STRING("13")>::type
  171. mpl_::integral_c<int, 13>
  172. `exp_parser1` is a [link metafunction_class template metafunction class] taking
  173. the input text as it's argument and it returns the integral representation of
  174. the number in the string. Try it with different numbers and see how it converts
  175. them.
  176. [section 3.1. Dealing with invalid input]
  177. [note Note that you can find everything that has been included and defined so far [link before_3_1 here].]
  178. Have you tried parsing an invalid input? Something that is not a number, such
  179. as:
  180. > exp_parser1::apply<BOOST_METAPARSE_STRING("thirteen")>::type
  181. << compilation error >>
  182. Well, `"thirteen"` ['is] a number, but our parser does not speak English, so it
  183. is considered as invalid input. As a result of this, compilation fails and you
  184. get a compilation error from Metashell.
  185. In the [@#dealing-with-invalid-input-1 Dealing with invalid input] section we
  186. will go into further details on error handling.
  187. [endsect]
  188. [section 3.2. Dealing with input containing more than what is needed]
  189. [note Note that you can find everything that has been included and defined so far [link before_3_2 here].]
  190. Let's try to give the parser two numbers instead of one:
  191. > exp_parser1::apply<BOOST_METAPARSE_STRING("11 13")>::type
  192. mpl_::integral_c<int, 11>
  193. You might be surprised by this: the parser did not return an error. It parsed
  194. the first number, `11` and ignored `13`. The way [link int_ `int_`] works is
  195. that it parses the number at the beginning of the input text and ignores the
  196. rest of the input.
  197. So `exp_parser1` has a bug: our little language consists of ['one] number, not a
  198. ['list of numbers]. Let's fix our parser to treat more than one numbers as an
  199. invalid input:
  200. > #include <boost/metaparse/entire_input.hpp>
  201. This gives us the [link entire_input `entire_input`] template class. We can
  202. wrap [link int_ `int_`] with [link entire_input `entire_input`] indicating
  203. that the number we parse with [link int_ `int_`] should be the entire input.
  204. Anything that comes after that is an error. So our parser is
  205. [link entire_input `entire_input`]`<`[link int_ `int_`]`>` now. Let's wrap it
  206. with [link build_parser `build_parser`]:
  207. > using exp_parser2 = build_parser<entire_input<int_>>;
  208. Let's try this new parser out:
  209. > exp_parser2::apply<BOOST_METAPARSE_STRING("13")>::type
  210. mpl_::integral_c<int, 13>
  211. It can still parse numbers. Let's try to give it two numbers:
  212. > exp_parser2::apply<BOOST_METAPARSE_STRING("11 13")>::type
  213. << compilation error >>
  214. This generates a compilation error, since the parser failed.
  215. [endsect]
  216. [section 3.3. Accepting optional whitespaces at the end of the input]
  217. [note Note that you can find everything that has been included and defined so far [link before_3_3 here].]
  218. Our parser became a bit too
  219. restrictive now. It doesn't allow ['anything] after the number, not even
  220. whitespaces:
  221. > exp_parser2::apply<BOOST_METAPARSE_STRING("11 ")>::type
  222. << compilation error >>
  223. Let's allow whitespaces after the number:
  224. > #include <boost/metaparse/token.hpp>
  225. This makes the [link token `token`] template class available. It takes a parser
  226. as its argument and allows optional whitespaces after that. Let's create a third
  227. parser allowing whitespaces after the number:
  228. > using exp_parser3 = build_parser<entire_input<token<int_>>>;
  229. We expect [link token `token`]`<`[link int_ `int_`]`>` to be the entire input
  230. in this case. We allow optional whitespaces after [link int_ `int_`] but
  231. nothing else:
  232. > exp_parser3::apply<BOOST_METAPARSE_STRING("11 ")>::type
  233. mpl_::integral_c<int, 11>
  234. [endsect]
  235. [endsect]
  236. [section 4. Parsing simple expressions]
  237. [note Note that you can find everything that has been included and defined so far [link before_4 here].]
  238. We can parse numbers. Let's try parsing something more complicated, such as
  239. `"11 + 2"`. This is a number followed by a `+` symbol followed by another
  240. number. [link int_ `int_`] (or [link token `token`]`<`[link int_ `int_`]`>`)
  241. implements the parser for one number.
  242. First, let's write a parser for the `+` symbol. We can use the following:
  243. > #include <boost/metaparse/lit_c.hpp>
  244. This gives us [link lit_c `lit_c`] which we can use to parse specific
  245. characters, such as `+`. The grammar parsing the `+` character can be
  246. represented by [link lit_c `lit_c`]`<'+'>`. To allow optional whitespaces after
  247. it, we should use [link token `token`]`<`[link lit_c `lit_c`]`<'+'>>`.
  248. So to parse `"11 + 2"` we need the following sequence of parsers:
  249. token<int_> token<lit_c<'+'>> token<int_>
  250. Metaparse provides [link sequence `sequence`] for parsing the sequence of
  251. things:
  252. > #include <boost/metaparse/sequence.hpp>
  253. We can implement the parser for our expressions using
  254. [link sequence `sequence`]:
  255. sequence<token<int_>, token<lit_c<'+'>>, token<int_>>
  256. Let's create a parser using it:
  257. > using exp_parser4 = build_parser<sequence<token<int_>, token<lit_c<'+'>>, token<int_>>>;
  258. Try parsing a simple expression using it:
  259. > exp_parser4::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
  260. boost::mpl::v_item<mpl_::integral_c<int, 2>, boost::mpl::v_item<mpl_::char_<'+'>
  261. , boost::mpl::v_item<mpl_::integral_c<int, 11>, boost::mpl::vector0<mpl_::na>, 0
  262. >, 0>, 0>
  263. What you get might look strange to you. It is a `vector` from [Boost.MPL](
  264. http://boost.org/libs/mpl). What you can see in the shell is the way this vector
  265. is represented. Metashell offers
  266. [pretty printing](metashell.org/manual/getting_started#data-structures-of-boostmpl)
  267. for [@http://boost.org/libs/mpl Boost.MPL] containers:
  268. > #include <metashell/formatter.hpp>
  269. After including this header, try parsing again:
  270. > exp_parser4::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
  271. boost_::mpl::vector<mpl_::integral_c<int, 11>, mpl_::char_<'+'>, mpl_::integral_c<int, 2> >
  272. What you get now looks more simple: this is a vector of three elements:
  273. * `mpl_::integral_c<int, 11>` This is the result of parsing with
  274. [link token `token`]`<`[link int_ `int_`]`>`.
  275. * `mpl_::char_<'+'>` This is the result of parsing with
  276. [link token `token`]`<`[link lit_c `lit_c`]`<'+'>>`.
  277. * `mpl_::integral_c<int, 2> >` This is the result of parsing with
  278. [link token `token`]`<`[link int_ `int_`]`>`.
  279. The result of parsing with a [link sequence `sequence`] is the `vector` of the
  280. individual parsing results.
  281. [section 4.1. Tokenizer]
  282. [note Note that you can find everything that has been included and defined so far [link before_4_1 here].]
  283. You might have noticed that our parsers have no separate tokenizers.
  284. Tokenization is part of the parsing process. However, it makes the code of the
  285. parsers cleaner if we separate the two layers. The previous example has two
  286. types of tokens:
  287. * a number (eg. `13`)
  288. * a `+` symbol
  289. In our last solution we parsed them by using the
  290. [link token `token`]`<`[@int_html `int_`]`>` and
  291. [link token `token`]`<`[link lit_c `lit_c`]`<'+'>>` parsers. Have you noticed
  292. a pattern? We wrap the parsers of the tokens with [link token `token`]`<...>`.
  293. It is not just syntactic sugar. Our tokens might be followed (separated) by
  294. whitespaces, which can be ignored. That is what [link token `token`]`<...>`
  295. implements.
  296. So let's make the implementation of `exp_parser` cleaner by separating the
  297. tokenization from the rest of the parser:
  298. > using int_token = token<int_>;
  299. > using plus_token = token<lit_c<'+'>>;
  300. [link getting_started_1 copy-paste friendly version]
  301. These two definitions create type aliases for the parsers of our tokens. For the
  302. compiler it doesn't matter if we use `plus_token` or
  303. [link token `token`]`<`[link lit_c `lit_c`]`<'+'>>`, since they refer to the
  304. same type. But it makes the code of the parser easier to understand.
  305. We can now define our expression parser using these tokens:
  306. > using exp_parser5 = build_parser<sequence<int_token, plus_token, int_token>>;
  307. We can use it the same way as `exp_parser4`:
  308. > exp_parser5::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
  309. boost_::mpl::vector<mpl_::integral_c<int, 11>, mpl_::char_<'+'>, mpl_::integral_c<int, 2> >
  310. [endsect]
  311. [section 4.2. Evaluating the expression]
  312. [note Note that you can find everything that has been included and defined so far [link before_4_2 here].]
  313. It would be nice if we could evaluate the expression as well. Instead of
  314. returning a `vector` as the result of parsing, we should return the evaluated
  315. expression. For example the result of parsing `"11 + 2"` should be
  316. `mpl_::integral_c<int, 13>`.
  317. Metaparse provides [link transform `transform`] which we can use to implement
  318. this:
  319. > #include <boost/metaparse/transform.hpp>
  320. This can be used to transform the result of a parser. For example we have the
  321. [link sequence `sequence`]`<int_token, plus_token, int_token>` parser which
  322. returns a `vector`. We want to transform this `vector` into a number, which is
  323. the result of evaluating the expression. We need to pass
  324. [link transform `transform`] the [link sequence `sequence`]`<...>` parser and
  325. a function which turns the `vector` into the result we need. First let's create
  326. this [link metafunction metafunction]:
  327. > #include <boost/mpl/plus.hpp>
  328. > #include <boost/mpl/at.hpp>
  329. > template <class Vector> \
  330. ...> struct eval_plus : \
  331. ...> boost::mpl::plus< \
  332. ...> typename boost::mpl::at_c<Vector, 0>::type, \
  333. ...> typename boost::mpl::at_c<Vector, 2>::type \
  334. ...> > {};
  335. [link getting_started_2 copy-paste friendly version]
  336. [note
  337. Note that if the last character of your command is the `\` character in
  338. Metashell, then the shell assumes that you will continue typing the same command
  339. and waits for that before evaluating your command. When Metashell is waiting for
  340. the second (or third, or fourth, etc) line of a command, it uses a special
  341. prompt, `...>`.
  342. ]
  343. What it does is that using `boost::mpl::at_c` it takes the first (index 0) and
  344. the third (index 2) elements of the `vector` that is the result of parsing with
  345. [link sequence `sequence`]`<...>` and adds them. We can try it out with an
  346. example `vector`:
  347. > eval_plus< \
  348. ...> boost::mpl::vector< \
  349. ...> mpl_::integral_c<int, 11>, \
  350. ...> mpl_::char_<'+'>, \
  351. ...> mpl_::integral_c<int, 2> \
  352. ...> >>::type
  353. mpl_::integral_c<int, 13>
  354. [link getting_started_3 copy-paste friendly version]
  355. We can use `eval_plus` to build a parser that evaluates the expression it
  356. parses:
  357. > #include <boost/mpl/quote.hpp>
  358. > using exp_parser6 = \
  359. ...> build_parser< \
  360. ...> transform< \
  361. ...> sequence<int_token, plus_token, int_token>, \
  362. ...> boost::mpl::quote1<eval_plus> \
  363. ...> > \
  364. ...> >;
  365. [link getting_started_4 copy-paste friendly version]
  366. [note
  367. Note that we have to use `boost::mpl::quote1` to turn our `eval_plus`
  368. [link metafunction metafunction] into a
  369. [link metafunction_class metafunction class].
  370. ]
  371. [link transform `transform`] parses the input using
  372. [link sequence `sequence`]`<int_token, plus_token, int_token>` and transforms
  373. the result of that using `eval_plus`. Let's try it out:
  374. > exp_parser6::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
  375. mpl_::integral_c<int, 13>
  376. We have created a simple expression parser. The following diagram shows how it
  377. works:
  378. [$images/metaparse/tutorial_diag0.png [width 50%]]
  379. The rounded boxes in the diagram are the parsers parsing the input, which are
  380. functions ([link metafunction_class template metafunction class]es). The arrows
  381. represent how the results are passed around between these parsers (they are the
  382. return values of the function calls).
  383. It uses [link sequence `sequence`] to parse the different elements (the first
  384. number, the `+` symbol and the second number) and builds a `vector`. The final
  385. result is calculated from that `vector` by the [link transform `transform`]
  386. parser.
  387. [endsect]
  388. [endsect]
  389. [section 5. Parsing longer expressions]
  390. [note Note that you can find everything that has been included and defined so far [link before_5 here].]
  391. We can parse simple expressions adding two numbers together. But we can't parse
  392. expressions adding three, four or maybe more numbers together. In this section
  393. we will implement a parser for expressions adding lots of numbers together.
  394. [section 5.1. Parsing a subexpression repeatedly]
  395. [note Note that you can find everything that has been included and defined so far [link before_5_1 here].]
  396. We can't solve this problem with [link sequence `sequence`], since we don't
  397. know how many numbers the input will have. We need a parser that:
  398. * parses the first number
  399. * keeps parsing `+ <number>` elements until the end of the input
  400. Parsing the first number is something we can already do: the `int_token` parser
  401. does it for us. Parsing the `+ <number>` elements is more tricky. Metaparse
  402. offers different tools for approaching this. The most simple is
  403. [link repeated `repeated`]:
  404. > #include <boost/metaparse/any.hpp>
  405. [link repeated `repeated`] needs a parser (which parses one `+ <number>`
  406. element) and it keeps parsing the input with it as long as it can. This will
  407. parse the entire input for us. Let's create a parser for our expressions using
  408. it:
  409. > using exp_parser7 = \
  410. ...> build_parser< \
  411. ...> sequence< \
  412. ...> int_token, /* The first <number> */ \
  413. ...> repeated<sequence<plus_token, int_token>> /* The "+ <number>" elements */ \
  414. ...> > \
  415. ...> >;
  416. [link getting_started_5 copy-paste friendly version]
  417. We have a [link sequence `sequence`] with two elements:
  418. * The first number (`int_token`)
  419. * The `+ <number>` parts
  420. The second part is an [link repeated `repeated`], which parses the `+ <number>`
  421. elements. One such element is parsed by
  422. [link sequence `sequence`]`<plus_token, int_token>`. This is just a sequence of
  423. the `+` symbol and the number.
  424. Let's try parsing an expression using this:
  425. > exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
  426. Here is a formatted version of the result which is easier to read:
  427. boost_::mpl::vector<
  428. // The result of int_token
  429. mpl_::integral_c<int, 1>,
  430. // The result of repeated< sequence<plus_token, int_token> >
  431. boost_::mpl::vector<
  432. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2> >,
  433. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3> >,
  434. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4> >
  435. >
  436. >
  437. The result is a `vector` of two elements. The first element of this `vector` is
  438. the result of parsing the input with `int_token`, the second element of this
  439. `vector` is the result of parsing the input with
  440. [link repeated `repeated`]`< `[link sequence `sequence`]`<plus_token, int_token>>`.
  441. This second element is also a `vector`. Each element of this `vector` is the
  442. result of parsing the input with
  443. [link sequence `sequence`]`<plus_token, int_token>` once. Here is a diagram
  444. showing how `exp_parser7` parses the input `1 + 2 + 3 + 4`:
  445. [$images/metaparse/tutorial_diag1.png [width 90%]]
  446. The diagram shows that the `+ <number>` elements are parsed by
  447. [link sequence `sequence`]`<plus_token, int_token>` elements and their results
  448. are collected by [link repeated `repeated`], which constructs a `vector` of
  449. these results. The value of the first `<number>` and this `vector` are placed in
  450. another `vector`, which is the result of parsing.
  451. [endsect]
  452. [section 5.2. Evaluating the parsed expression]
  453. [note Note that you can find everything that has been included and defined so far [link before_5_2 here].]
  454. The final result here is a pair of the first number and the `vector` of the rest
  455. of the values. To calculate the result we need to process that data structure.
  456. Let's give the example output we have just parsed a name. This will make it
  457. easier to test the code calculating the final result from this structure:
  458. > using temp_result = exp_parser7::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type;
  459. Now we can write a [link metafunction template metafunction] turning this
  460. structure into the result of the calculation this structure represents.
  461. [section 5.2.1. Learning about `boost::mpl::fold`]
  462. [note Note that you can find everything that has been included and defined so far [link before_5_2_1 here].]
  463. We have a `vector` containing
  464. another `vector`. Therefore, we will need to be able to summarise the elements
  465. of different `vector`s. We can use the `boost::mpl::fold`
  466. [link metafunction metafunction] to do this:
  467. > #include <boost/mpl/fold.hpp>
  468. With this [link metafunction metafunction], we can iterate over a `vector` of
  469. parsed numbers and summarise them. We can provide it a
  470. [link metafunction metafunction] taking two arguments: the sum we have so far
  471. and the next element of the `vector`. This [link metafunction metafunction]
  472. will be called for every element of the `vector`.
  473. [note
  474. Note that this is very similar to the `std::accumulate` algorithm.
  475. [@http://boost.org/libs/mpl Boost.MPL] provides `boost::mpl::accumulate` as
  476. well, which is a synonym for `boost::mpl::fold`. This tutorial (and Metaparse)
  477. uses the name `fold`.
  478. ]
  479. Let's start with a simple case: a `vector` of numbers. For example let's
  480. summarise the elements of the following `vector`:
  481. > using vector_of_numbers = \
  482. ...> boost::mpl::vector< \
  483. ...> boost::mpl::int_<2>, \
  484. ...> boost::mpl::int_<5>, \
  485. ...> boost::mpl::int_<6> \
  486. ...> >;
  487. [link getting_started_6 copy-paste friendly version]
  488. We will write a [link metafunction template metafunction], `sum_vector` for
  489. summarising the elements of a `vector` of numbers:
  490. > template <class Vector> \
  491. ...> struct sum_vector : \
  492. ...> boost::mpl::fold< \
  493. ...> Vector, \
  494. ...> boost::mpl::int_<0>, \
  495. ...> boost::mpl::lambda< \
  496. ...> boost::mpl::plus<boost::mpl::_1, boost::mpl::_2> \
  497. ...> >::type \
  498. ...> > \
  499. ...> {};
  500. [link getting_started_7 copy-paste friendly version]
  501. This [link metafunction metafunction] takes the `vector` to summarise the
  502. elements of as its argument and uses `boost::mpl::fold` to calculate the sum.
  503. `boost::mpl::fold` takes three arguments:
  504. * The container to summarise. This is `Vector`.
  505. * The starting value for ['the sum we have so far]. Using `0` means that we want
  506. to start the sum from `0`.
  507. * The function to call in every iteration while looping over the container. We
  508. are using a
  509. [@http://www.boost.org/libs/mpl/doc/refmanual/lambda-expression.html lambda expression]
  510. in our example, which is the expression wrapped by `boost::mpl::lambda`. This
  511. expression adds its two arguments together using `boost::mpl::plus`. The
  512. lambda expression refers to its arguments by `boost::mpl::_1` and
  513. `boost::mpl::_2`.
  514. Let's try this [link metafunction metafunction] out:
  515. > sum_vector<vector_of_numbers>::type
  516. mpl_::integral_c<int, 13>
  517. It works as expected. Here is a diagram showing how it works:
  518. [$images/metaparse/tutorial_diag2.png [width 50%]]
  519. As the diagram shows, `boost::mpl::fold` evaluates the lambda expression for
  520. each element of the `vector` and passes the result of the previous evaluation to
  521. the next lambda expression invocation.
  522. We have a [link metafunction metafunction] that can summarise a `vector` of
  523. numbers. The result of parsing the `+ <number>` elements is a `vector` of
  524. `vector`s. As a recap, here is `temp_result`:
  525. boost_::mpl::vector<
  526. // The result of int_token
  527. mpl_::integral_c<int, 1>,
  528. // The result of repeated< sequence<plus_token, int_token> >
  529. boost_::mpl::vector<
  530. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2> >,
  531. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3> >,
  532. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4> >
  533. >
  534. >
  535. First let's summarise the result of [link repeated `repeated`]`<...>` using
  536. `boost::mpl::fold`. This is a `vector` of `vector`s, but that's fine.
  537. `boost::mpl::fold` doesn't care about what the elements of the `vector` are.
  538. They can be numbers, `vector`s or something else as well. The function we use to
  539. add two numbers together (which was a lambda expression in our previous example)
  540. gets these elements as its argument and has to deal with them. So to summarise
  541. the elements of the `vector`s we get as the result of parsing with
  542. [link repeated `repeated`]`<...>`, we need to write a
  543. [link metafunction metafunction] that can deal with these elements. One such
  544. element is `boost_::mpl::vector<mpl_::char<'+'>, mpl_::integral_c<int, 2>>`.
  545. Here is a [link metafunction metafunction] that can be used in a
  546. `boost::mpl::fold`:
  547. > template <class Sum, class Item> \
  548. ...> struct sum_items : \
  549. ...> boost::mpl::plus< \
  550. ...> Sum, \
  551. ...> typename boost::mpl::at_c<Item, 1>::type \
  552. ...> > \
  553. ...> {};
  554. [link getting_started_8 copy-paste friendly version]
  555. This function takes two arguments:
  556. * `Sum`, which is a number. This is the summary of the already processed
  557. elements.
  558. * `Item`, the next item of the `vector`. These items are `vector`s of size two:
  559. the result of parsing the `+` symbol and the number.
  560. The [link metafunction metafunction] adds the sum we have so far and the next
  561. number together using the `boost::mpl::plus` [link metafunction metafunction].
  562. To get the next number out of `Item`, it uses `boost::mpl::at_c`. Let's try
  563. `sum_items` out:
  564. > sum_items< \
  565. ...> mpl_::integral_c<int, 1>, \
  566. ...> boost::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>> \
  567. ...> >::type
  568. mpl_::integral_c<int, 3>
  569. [link getting_started_9 copy-paste friendly version]
  570. We have called `sum_items` with values from `temp_result` and saw that it works
  571. as expected: it added the partial sum (`mpl_::integral_c<int, 1>`) to the next
  572. number (`mpl_::integral_c<int, 2>`).
  573. `boost::mpl::fold` can summarise the list we get as the result of parsing the
  574. `+ <number>` elements of the input, so we need to extract this list from
  575. `temp_result` first:
  576. > boost::mpl::at_c<temp_result, 1>::type
  577. Here is the formatted version of the result:
  578. boost_::mpl::vector<
  579. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 2>>,
  580. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 3>>,
  581. boost_::mpl::vector<mpl_::char_<'+'>, mpl_::integral_c<int, 4>>
  582. >
  583. This is the second element of the `temp_result` vector (the first one is the
  584. value of the first `<number>` element). Let's try fold out for this:
  585. > \
  586. ...> boost::mpl::fold< \
  587. ...> boost::mpl::at_c<temp_result, 1>::type, /* The vector to summarise */ \
  588. ...> boost::mpl::int_<0>, /* The value to start the sum from */ \
  589. ...> boost::mpl::quote2<sum_items> /* The function to call in each iteration */ \
  590. ...> >::type
  591. mpl_::integral_c<int, 9>
  592. [link getting_started_10 copy-paste friendly version]
  593. [note
  594. We are using `sum_items` as the function to call in each iteration. We are
  595. passing a [link metafunction metafunction] (`sum_items`) to another
  596. [link metafunction metafunction] (`boost::mpl::fold`) as an argument. To be
  597. able to do this, we need to turn it into a
  598. [link metafunction_class template metafunction class] using
  599. `boost::mpl::quote2` (`2` means that it takes two arguments).
  600. ]
  601. As we have seen, the result of this is the sum of the elements, which was `9` in
  602. our case. Here is a diagram showing how `boost::mpl::fold` works:
  603. [$images/metaparse/tutorial_diag3.png [width 50%]]
  604. It starts with the value `boost::mpl::int_<0>` and adds the elements of the
  605. `boost_::mpl::vector` containing the parsing results one by one. The diagram
  606. shows how the subresults are calculated and then used for further calculations.
  607. [endsect]
  608. [section 5.2.2. Evaluating the expression using `boost::mpl::fold`]
  609. [note Note that you can find everything that has been included and defined so far [link before_5_2_2 here].]
  610. Let's use `sum_items` with `boost::mpl::fold` to build the parser that
  611. summarises the values coming from the `+ <number>` elements. We can extend the
  612. parser we were using in `exp_parser7` by wrapping the
  613. [link repeated `repeated`]`<...>` part with [link transform `transform`], which
  614. transforms the result of [link repeated `repeated`]`<...>` with the folding
  615. expression we have just created:
  616. > using exp_parser8 = \
  617. ...> build_parser< \
  618. ...> sequence< \
  619. ...> int_token, /* parse the first <number> */ \
  620. ...> transform< \
  621. ...> repeated<sequence<plus_token, int_token>>, /* parse the "+ <number>" elements */ \
  622. ...> \
  623. ...> /* lambda expression summarising the "+ <number>" elements using fold */ \
  624. ...> boost::mpl::lambda< \
  625. ...> /* The folding expression we have just created */ \
  626. ...> boost::mpl::fold< \
  627. ...> boost::mpl::_1, /* the argument of the lambda expression, the result */ \
  628. ...> /* of the repeated<...> parser */ \
  629. ...> boost::mpl::int_<0>, \
  630. ...> boost::mpl::quote2<sum_items> \
  631. ...> > \
  632. ...> >::type \
  633. ...> > \
  634. ...> > \
  635. ...> >;
  636. [link getting_started_11 copy-paste friendly version]
  637. It uses [link transform `transform`] to turn the result of the previous version
  638. of our parser into one that summarises the `+ <number>` elements. Let's try it
  639. out:
  640. > exp_parser8::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
  641. boost_::mpl::vector<mpl_::integral_c<int, 1>, mpl_::integral_c<int, 9> >
  642. This returns a pair of numbers as the result of parsing: the first number and
  643. the sum of the rest. To get the value of the entire expression we need to add
  644. these two numbers together. We can extend our parser to do this final addition
  645. as well:
  646. > using exp_parser9 = \
  647. ...> build_parser< \
  648. ...> transform< \
  649. ...> /* What we had so far */ \
  650. ...> sequence< \
  651. ...> int_token, \
  652. ...> transform< \
  653. ...> repeated<sequence<plus_token, int_token>>, \
  654. ...> boost::mpl::lambda< \
  655. ...> boost::mpl::fold< \
  656. ...> boost::mpl::_1, \
  657. ...> boost::mpl::int_<0>, \
  658. ...> boost::mpl::quote2<sum_items> \
  659. ...> > \
  660. ...> >::type \
  661. ...> > \
  662. ...> >, \
  663. ...> boost::mpl::quote1<sum_vector> /* summarise the vector of numbers */ \
  664. ...> > \
  665. ...> >;
  666. [link getting_started_12 copy-paste friendly version]
  667. `exp_parser9` wraps the parser we had so far (which gives us the two element
  668. `vector` as the result) with [link transform `transform`] to add the elements
  669. of that two element `vector` together. Since that two element `vector` is a
  670. `vector` of numbers, we can (re)use the `sum_vector`
  671. [link metafunction metafunction] for this. Let's try it out:
  672. > exp_parser9::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
  673. mpl_::integral_c<int, 10>
  674. It gives us the correct result, but it is very inefficient. Let's see why:
  675. [$images/metaparse/tutorial_diag4.png [width 90%]]
  676. There are two loops in this process:
  677. * first [link repeated `repeated`] loops over the input to parse all of the
  678. `+ <number>` elements. It builds a `vector` during this. (`Loop 1` on the
  679. diagram)
  680. * then `boost::mpl::fold` loops over this `vector` to summarise the elements.
  681. (`Loop 2` on the diagram)
  682. [note
  683. Note that we have been talking about ['loop]s while there is no such thing as
  684. a loop in template metaprogramming. Loops can be implemented using
  685. ['recursion]: every recursive call is one iteration of the loop. The loop is
  686. stopped at the bottom of the recursive chain.
  687. ]
  688. [endsect]
  689. [section 5.2.3. Using a folding parser combinator]
  690. [note Note that you can find everything that has been included and defined so far [link before_5_2_3 here].]
  691. It would be nice, if the two loops could be merged together and the temporary
  692. `vector` wouldn't have to be built in the middle (don't forget: there is no
  693. such thing as a ['garbage collector] for template metaprogramming. Once you
  694. instantiate a template, it will be available until the end of ... the
  695. compilation).
  696. Metaparse provides the [link foldl `foldl`] parser combinator:
  697. > #include <boost/metaparse/foldl.hpp>
  698. It is almost the same as `boost::mpl::fold`, but instead of taking the `vector`
  699. as its first argument, which was coming from the repeated application of a
  700. parser ([link sequence `sequence`]`<plus_token, int_token>`) on the input, it
  701. takes the parser itself. [link foldl `foldl`] parses the input and calculates
  702. the summary on the fly. Here is how we can write our parser using it:
  703. > using exp_parser10 = \
  704. ...> build_parser< \
  705. ...> transform< \
  706. ...> sequence< \
  707. ...> int_token, \
  708. ...> foldl< \
  709. ...> sequence<plus_token, int_token>, \
  710. ...> boost::mpl::int_<0>, \
  711. ...> boost::mpl::quote2<sum_items> \
  712. ...> > \
  713. ...> >, \
  714. ...> boost::mpl::quote1<sum_vector>> \
  715. ...> >;
  716. [link getting_started_13 copy-paste friendly version]
  717. Here are the formatted versions of `exp_parser9` and `exp_parser10`
  718. side-by-side:
  719. // exp_parser9 exp_parser10
  720. build_parser< build_parser<
  721. transform< transform<
  722. sequence< sequence<
  723. int_token, int_token,
  724. transform< foldl<
  725. repeated<sequence<plus_token, int_token>>, sequence<plus_token, int_token>,
  726. boost::mpl::lambda<
  727. boost::mpl::fold<
  728. boost::mpl::_1,
  729. boost::mpl::int_<0>, boost::mpl::int_<0>,
  730. boost::mpl::quote2<sum_items> boost::mpl::quote2<sum_items>
  731. >
  732. >::type
  733. > >
  734. >, >,
  735. boost::mpl::quote1<sum_vector> boost::mpl::quote1<sum_vector>
  736. > >
  737. > >
  738. [link getting_started_14 copy-paste friendly version]
  739. In `exp_parser10` the "_[link repeated `repeated`] and then
  740. [link transform `transform`] with `boost::mpl::fold`_" part (the middle block of
  741. `exp_parser9`) has been replaced by one [link foldl `foldl`] parser that does
  742. the same thing but without building a `vector` in the middle. The same starting
  743. value (`boost::mpl::int_<0>`) and callback function (`sum_items`) could be used.
  744. Here is a diagram showing how `exp_parser10` works:
  745. [$images/metaparse/tutorial_diag5.png [width 90%]]
  746. In this case, the results of the
  747. [link sequence `sequence`]`<plus_token, int_token>` parsers are passed directly
  748. to a folding algorithm without an intermediate `vector`. Here is a diagram
  749. showing `exp_parser9` and `exp_parser10` side-by-side to make it easier to see
  750. the difference:
  751. [$images/metaparse/tutorial_diag6.png [width 90%]]
  752. [endsect]
  753. [section 5.2.4. Processing the initial element with the folding parser combinator]
  754. [note Note that you can find everything that has been included and defined so far [link before_5_2_4 here].]
  755. This solution can still be improved. The [link foldl `foldl`] summarising the
  756. `+ <number>` elements starts from `0` and once this is done, we add the value of
  757. the first `<number>` of the input to it in the first iteration. It would be more
  758. straightforward if [link foldl `foldl`] could use the value of the first
  759. `<number>` as the initial value of the "['sum we have so far]". Metaparse
  760. provides [link foldl_start_with_parser `foldl_start_with_parser`] for this:
  761. > #include <boost/metaparse/foldl_start_with_parser.hpp>
  762. [link foldl_start_with_parser `foldl_start_with_parser`] is almost the same as
  763. [link foldl `foldl`]. The difference is that instead of taking a starting
  764. ['value] for the sum it takes a ['parser]. First it parses the input with this
  765. parser and uses the value it returns as the starting value. Here is how we can
  766. implement our parser using it:
  767. > using exp_parser11 = \
  768. ...> build_parser< \
  769. ...> foldl_start_with_parser< \
  770. ...> sequence<plus_token, int_token>, /* apply this parser repeatedly */ \
  771. ...> int_token, /* use this parser to get the initial value */ \
  772. ...> boost::mpl::quote2<sum_items> /* use this function to add a new value to the summary */ \
  773. ...> > \
  774. ...> >;
  775. [link getting_started_15 copy-paste friendly version]
  776. This version of `exp_parser` uses
  777. [link foldl_start_with_parser `foldl_start_with_parser`]. This implementation is
  778. more compact than the earlier versions. There is no [link sequence `sequence`]
  779. element in this: the first `<number>` is parsed by `int_token` and its value is
  780. used as the initial value for the summary. Let's try it out:
  781. > exp_parser11::apply<BOOST_METAPARSE_STRING("1 + 2 + 3 + 4")>::type
  782. mpl_::integral_c<int, 10>
  783. It returns the same result as the earlier version but works differently. Here is
  784. a diagram showing how this implementation works:
  785. [$images/metaparse/tutorial_diag7.png [width 90%]]
  786. [endsect]
  787. [endsect]
  788. [endsect]
  789. [section 6. Adding support for other operators]
  790. [note Note that you can find everything that has been included and defined so far [link before_6 here].]
  791. Our parsers now support expressions adding numbers together. In this section we
  792. will add support for the `-` operator, so expressions like `1 + 2 - 3` can be
  793. evaluated.
  794. [section 6.1. Parsing expressions containing `-` operators]
  795. [note Note that you can find everything that has been included and defined so far [link before_6_1 here].]
  796. Currently we use the `plus_token` for parsing "the" operator, which has to be
  797. `+`. We can define a new token for parsing the `-` symbol:
  798. > using minus_token = token<lit_c<'-'>>;
  799. We need to build a parser that accepts either a `+` or a `-` symbol. This can be
  800. implemented using [link one_of `one_of`]:
  801. > #include <boost/metaparse/one_of.hpp>
  802. [link one_of `one_of`]`<plus_token, minus_token>` is a parser which accepts
  803. either a `+` (using `plus_token`) or a `-` (using `minus_token`) symbol. The
  804. result of parsing is the result of the parser that succeeded.
  805. [note
  806. You can give any parser to [link one_of `one_of`], therefore it is possible
  807. that more than one of them can parse the input. In those cases the order
  808. matters: [link one_of `one_of`] tries parsing the input with the parsers from
  809. left to right and the first one that succeeds, wins.
  810. ]
  811. Using this, we can make our parser accept subtractions as well:
  812. > using exp_parser12 = \
  813. ...> build_parser< \
  814. ...> foldl_start_with_parser< \
  815. ...> sequence<one_of<plus_token, minus_token>, int_token>, \
  816. ...> int_token, \
  817. ...> boost::mpl::quote2<sum_items> \
  818. ...> > \
  819. ...> >;
  820. [link getting_started_16 copy-paste friendly version]
  821. It uses [link one_of `one_of`]`<plus_token, minus_token>` as the separator for
  822. the numbers. Let's try it out:
  823. > exp_parser12::apply<BOOST_METAPARSE_STRING("1 + 2 - 3")>::type
  824. mpl_::integral_c<int, 6>
  825. The result is not correct. The reason for this is that `sum_items`, the function
  826. we summarise with ignores which operator was used and assumes that it is always
  827. `+`.
  828. [endsect]
  829. [section 6.2. Evaluating expressions containing `-` operators]
  830. [note Note that you can find everything that has been included and defined so far [link before_6_2 here].]
  831. To fix the evaluation of expressions containing subtractions, we need to fix
  832. the function we use for summarising. We need to write a version that takes the
  833. operator being used into account.
  834. First of all we will need the `boost::mpl::minus`
  835. [link metafunction metafunction] for implementing subtraction:
  836. > #include <boost/mpl/minus.hpp>
  837. Let's write a helper metafunction that takes three arguments: the left operand,
  838. the operator and the right operand:
  839. > template <class L, char Op, class R> struct eval_binary_op;
  840. > template <class L, class R> struct eval_binary_op<L, '+', R> : boost::mpl::plus<L, R>::type {};
  841. > template <class L, class R> struct eval_binary_op<L, '-', R> : boost::mpl::minus<L, R>::type {};
  842. [link getting_started_17 copy-paste friendly version]
  843. The first command declares the `eval_binary_op` metafunction. The first and
  844. third arguments are the left and right operands and the second argument is the
  845. operator.
  846. [note
  847. Note that it does not satisfy the expectations of a
  848. [link metafunction template metafunction] since it takes the operator as a
  849. `char` and not as a `class` (or `typename`) argument. For simplicity, we will
  850. still call it a metafunction.
  851. ]
  852. The second and third commands define the operation for the cases when the
  853. operator is `+` and `-`. When the `eval_binary_op` metafunction is called,
  854. the C++ compiler chooses one of the definitions based on the operator. If you
  855. have functional programming experience this approach (pattern matching) might be
  856. familiar to you. Let's try `eval_binary_op` out:
  857. > eval_binary_op<boost::mpl::int_<11>, '+', boost::mpl::int_<2>>::type
  858. mpl_::integral_c<int, 13>
  859. > eval_binary_op<boost::mpl::int_<13>, '-', boost::mpl::int_<2>>::type
  860. mpl_::integral_c<int, 11>
  861. [link getting_started_18 copy-paste friendly version]
  862. You might also try to use it with an operator it does not expect (yet). For
  863. example `'*'`. You will see the C++ compiler complaining about that the
  864. requested version of the `eval_binary_op` template has not been defined. This
  865. solution can be extended and support for the `'*'` operator can always be added
  866. later.
  867. Let's write the [link metafunction metafunction] we can use from the folding
  868. parser to evaluate the expressions using `+` and `-` operators. This takes two
  869. arguments:
  870. * The partial result we have evaluated so far. (This used to be the summary we
  871. have evaluated so far, but we are making it a more general evaluation now).
  872. This is the left operand, a number.
  873. * The result of parsing `(+|-) <number>`. This a `vector` containing two
  874. elements: a character representing the operator (`+` or `-`) and the value of
  875. the `<number>`. The number is the right operand.
  876. Let's write the [link metafunction metafunction] `binary_op` that takes these
  877. arguments and calls `eval_binary_op`:
  878. > template <class S, class Item> \
  879. ...> struct binary_op : \
  880. ...> eval_binary_op< \
  881. ...> S, \
  882. ...> boost::mpl::at_c<Item, 0>::type::value, \
  883. ...> typename boost::mpl::at_c<Item, 1>::type \
  884. ...> > \
  885. ...> {};
  886. [link getting_started_19 copy-paste friendly version]
  887. This [link metafunction metafunction] takes the operator (the first element)
  888. and the right operand (the second element) from `Item`. The operator is a class
  889. representing a character, such as `mpl_::char_<'+'>`. To get the character value
  890. out of it, one has to access its `::value`. For example `mpl_::char<'+'>::value`
  891. is `'+'`. Since `eval_binary_op` takes this character value as its second
  892. argument, we had to pass `boost::mpl::at_c<Item, 0>::type::value` to it. Let's
  893. try it out:
  894. > binary_op<boost::mpl::int_<11>, boost::mpl::vector<boost::mpl::char_<'+'>, boost::mpl::int_<2>>>::type
  895. mpl_::integral_c<int, 13>
  896. We passed it a number (`11`) and a `vector` of a character (`+`) and another
  897. number (`2`). It added the two numbers as expected. Let's use this function as
  898. the third argument of [link foldl_start_with_parser `foldl_start_with_parser`]:
  899. > using exp_parser13 = \
  900. ...> build_parser< \
  901. ...> foldl_start_with_parser< \
  902. ...> sequence<one_of<plus_token, minus_token>, int_token>, \
  903. ...> int_token, \
  904. ...> boost::mpl::quote2<binary_op> \
  905. ...> > \
  906. ...> >;
  907. [link getting_started_20 copy-paste friendly version]
  908. It uses `binary_op` instead of `sum_items`. Let's try it out:
  909. > exp_parser13::apply<BOOST_METAPARSE_STRING("1 + 2 - 3")>::type
  910. mpl_::integral_c<int, 0>
  911. It returns the correct result.
  912. [endsect]
  913. [endsect]
  914. [section 7. Dealing with precedence]
  915. [note Note that you can find everything that has been included and defined so far [link before_7 here].]
  916. We support addition and subtraction. Let's support multiplication as well.
  917. [section 7.1. Adding support for the `*` operator]
  918. [note Note that you can find everything that has been included and defined so far [link before_7_1 here].]
  919. We can extend the solution we have built for addition and subtraction. To do
  920. that, we need to add support for multiplication to `eval_binary_op`:
  921. > #include <boost/mpl/times.hpp>
  922. > template <class L, class R> struct eval_binary_op<L, '*', R> : boost::mpl::times<L, R>::type {};
  923. [link getting_started_21 copy-paste friendly version]
  924. We had to include `<boost/mpl/times.hpp>` to get the `boost::mpl::times`
  925. [link metafunction metafunction] and then we could extend `eval_binary_op` to
  926. support the `*` operator as well. We can try it out:
  927. > eval_binary_op<boost::mpl::int_<3>, '*', boost::mpl::int_<4>>::type
  928. mpl_::integral_c<int, 12>
  929. This works as expected. Let's create a token for parsing the `*` symbol:
  930. > using times_token = token<lit_c<'*'>>;
  931. Now we can extend our parser to accept the `*` symbol as an operator:
  932. > using exp_parser14 = \
  933. ...> build_parser< \
  934. ...> foldl_start_with_parser< \
  935. ...> sequence<one_of<plus_token, minus_token, times_token>, int_token>, \
  936. ...> int_token, \
  937. ...> boost::mpl::quote2<binary_op> \
  938. ...> > \
  939. ...> >;
  940. [link getting_started_22 copy-paste friendly version]
  941. This version accepts either a `+`, a `-` or a `*` symbol as the operator. Let's
  942. try this out:
  943. > exp_parser14::apply<BOOST_METAPARSE_STRING("2 * 3")>::type
  944. mpl_::integral_c<int, 6>
  945. This works as expected. Let's try another, slightly more complicated expression:
  946. > exp_parser14::apply<BOOST_METAPARSE_STRING("1 + 2 * 3")>::type
  947. mpl_::integral_c<int, 9>
  948. This returns a wrong result. The value of this expression should be `7`, not
  949. `9`. The problem with this is that our current implementation does not take
  950. operator precedence into account. It treats this expression as `(1 + 2) * 3`
  951. while we expect it to be `1 + (2 * 3)` since addition has higher precedence than
  952. multiplication.
  953. [endsect]
  954. [section 7.2. Adding support for precedence of operators]
  955. [note Note that you can find everything that has been included and defined so far [link before_7_2 here].]
  956. Let's make it possible for different operators to have different precedence. To
  957. do this, we define a new parser for parsing expressions containing only `*`
  958. operators (that is the operator with the lowest precedence):
  959. > using mult_exp1 = foldl_start_with_parser<sequence<times_token, int_token>, int_token, boost::mpl::quote2<binary_op>>;
  960. `mult_exp1` can parse expressions containing only `*` operator. For example
  961. `3 * 2` or `6 * 7 * 8`. Now we can create a parser supporting only the `+` and
  962. `-` operators but instead of separating ['numbers] with these operators we will
  963. separate ['expressions containing only `*` operators]. This means that the
  964. expression `1 * 2 + 3 * 4` is interpreted as the expressions `1 * 2` and `3 * 4`
  965. separated by a `+` operator. A number (eg. `13`) is the special case of an
  966. ['expression containing only `*` operators].
  967. Here is the parser implementing this:
  968. > using exp_parser15 = \
  969. ...> build_parser< \
  970. ...> foldl_start_with_parser< \
  971. ...> sequence<one_of<plus_token, minus_token>, mult_exp1>, \
  972. ...> mult_exp1, \
  973. ...> boost::mpl::quote2<binary_op> \
  974. ...> > \
  975. ...> >;
  976. [link getting_started_23 copy-paste friendly version]
  977. Note that this is almost the same as `exp_parser13`. The only difference is that
  978. it uses `mult_exp1` everywhere, where `exp_parser13` was using `int_token`.
  979. Let's try it out:
  980. > exp_parser15::apply<BOOST_METAPARSE_STRING("1 + 2 * 3")>::type
  981. mpl_::integral_c<int, 7>
  982. This takes the precedence rules into account. The following diagram shows how it
  983. works:
  984. [$images/metaparse/tutorial_diag8.png [width 80%]]
  985. Subexpressions using `*` operators only are evaluated (by `mult_exp1`) and
  986. treated as single units while interpreting expressions using `+` and `-`
  987. operators. Numbers not surrounded by `*` operators are treated also as operators
  988. using `*` only (containing no operations but a number).
  989. If you need more layers (eg. introducing the `^` operator) you can extend this
  990. solution with further layers. The order of the layers determine the precedence
  991. of the operators.
  992. [endsect]
  993. [endsect]
  994. [section 8. Dealing with associativity]
  995. [note Note that you can find everything that has been included and defined so far [link before_8 here].]
  996. Let's add division to our calculator language. Since it has the same precedence
  997. as multiplication, it should be added to that layer:
  998. > #include <boost/mpl/divides.hpp>
  999. > template <class L, class R> struct eval_binary_op<L, '/', R> : boost::mpl::divides<L, R>::type {};
  1000. > using divides_token = token<lit_c<'/'>>;
  1001. > using mult_exp2 = \
  1002. ...> foldl_start_with_parser< \
  1003. ...> sequence<one_of<times_token, divides_token>, int_token>, \
  1004. ...> int_token, \
  1005. ...> boost::mpl::quote2<binary_op> \
  1006. ...> >;
  1007. > using exp_parser16 = \
  1008. ...> build_parser< \
  1009. ...> foldl_start_with_parser< \
  1010. ...> sequence<one_of<plus_token, minus_token>, mult_exp2>, \
  1011. ...> mult_exp2, \
  1012. ...> boost::mpl::quote2<binary_op> \
  1013. ...> > \
  1014. ...> >;
  1015. [link getting_started_24 copy-paste friendly version]
  1016. We have to include `<boost/mpl/divides.hpp>` to get a
  1017. [link metafunction metafunction] for doing a division. We need to extend the
  1018. `eval_binary_op` [link metafunction metafunction] to support division as well.
  1019. We had to introduce a new token, `divides_token` that can parse the `/` symbol.
  1020. We have extended `mult_exp1` to accept either a `times_token` or a
  1021. `divides_token` as the operator. This extended parser is called `mult_exp2`.
  1022. We have written a new parser, `exp_parser16` which is the same as `exp_parser15`
  1023. but uses `mult_exp2` instead of `mult_exp1`. This can parse expressions using
  1024. division as well (and this new operator has the right precedence). Let's try it
  1025. out:
  1026. > exp_parser16::apply<BOOST_METAPARSE_STRING("8 / 4")>::type
  1027. mpl_::integral_c<int, 2>
  1028. This works as expected. But what should be the value of `8 / 4 / 2`? The answer
  1029. can be either `1` or `4` depending on the associativity of the division
  1030. operator. If it is left associative, then this expressions is interpreted as
  1031. `(8 / 4) / 2` and the result is `1`. If it is right associative, this
  1032. expression is interpreted as `8 / (4 / 2)` and the result is `4`.
  1033. Try to guess which result our current implementation gives before trying it
  1034. out. Once you have verified the current behaviour, continue reading.
  1035. [section 8.1. Understanding the current implementation]
  1036. [note Note that you can find everything that has been included and defined so far [link before_8_1 here].]
  1037. Here is a diagram showing how our current parser processes the expression
  1038. `8 / 4 / 2`:
  1039. [$images/metaparse/tutorial_diag8.png [width 70%]]
  1040. It takes the first number, `8`, divides it by the second one, `4` and then it
  1041. divides the result with the third one, `2`. This means, that in our current
  1042. implementation, division is left associative: `8 / 4 / 2` means `(8 / 4) / 2`.
  1043. Another thing to note is that the initial value is `8` and the list of values
  1044. [link foldl `foldl`] iterates over is "`/ 4`", "`/ 2`".
  1045. [endsect]
  1046. [section 8.2. Folding in reverse order]
  1047. [note Note that you can find everything that has been included and defined so far [link before_8_2 here].]
  1048. [link foldl `foldl`] applies a parser repeatedly and iterates over the parsing
  1049. results from ['left] to right. (This is where the `l` in the name comes from).
  1050. Metaparse provides another folding parser combinator, [link foldr `foldr`]. It
  1051. applies a parser on the input as well but it iterates from ['right] to left over
  1052. the results.
  1053. Similarly to [link foldl_start_with_parser `foldl_start_with_parser`], Metaparse
  1054. provides [link foldr_start_with_parser `foldr_start_with_parser`] as well. A
  1055. major difference between the two
  1056. ([link foldl_start_with_parser `foldl_start_with_parser`] and
  1057. [link foldr_start_with_parser `foldr_start_with-parser`]) solutions is that
  1058. while [link foldl_start_with_parser `foldl_start_with_parser`] treats the
  1059. ['first] number as a special one,
  1060. [link foldr_start_with_parser `foldr_start_with_parser`] treats the ['last]
  1061. number as a special one. This might sound strange, but think about it: if you
  1062. want to summarise the elements from right to left, your starting value should be
  1063. the last element, not the first one, as the first one is the one you visit last.
  1064. Due to the above difference
  1065. [link foldr_start_with_parser `foldr_start_with_parser`] is not a drop-in
  1066. replacement of [link foldl_start_with_parser `foldl_start_with_parser`]. While
  1067. the list of values [link foldl `foldl`] was iterating over is "`8`", "`/ 4`",
  1068. "`/ 2`", the list of values [link foldr `foldlr`] has to iterate over is "`2`",
  1069. "`4 /`", "`8 /`".
  1070. This means that the function we use to ['"add"] a new value to the already
  1071. evaluated part of the expression (this has been `binary_op` so far) has to be
  1072. prepared for taking the next operator and operand in a reverse order (eg. by
  1073. taking "`4 /`" instead of "`/ 4`"). We write another
  1074. [link metafunction metafunction] for this purpose:
  1075. > template <class S, class Item> \
  1076. ...> struct reverse_binary_op : \
  1077. ...> eval_binary_op< \
  1078. ...> typename boost::mpl::at_c<Item, 0>::type, \
  1079. ...> boost::mpl::at_c<Item, 1>::type::value, \
  1080. ...> S \
  1081. ...> > \
  1082. ...> {};
  1083. [link getting_started_25 copy-paste friendly version]
  1084. There are multiple differences between `binary_op` and `reverse_binary_op`:
  1085. * The `Item` argument, which is a `vector` is expected to be
  1086. `[operator, operand]` in `binary_op` and `[operand, operator]` in
  1087. `reverse_binary_op`.
  1088. * Both versions use `eval_binary_op` to evaluate the subexpression, but
  1089. `binary_op` treats `S`, the value representing the already evaluated part of
  1090. the expression as the left operand, while `reverse_binary_op` treats it as the
  1091. right operand. This is because in the first case we are going from left to
  1092. right while in the second case we are going from right to left.
  1093. We need to include [link foldr_start_with_parser `foldr_start_with_parser`]:
  1094. > #include <boost/metaparse/foldr_start_with_parser.hpp>
  1095. We can rewrite `mult_exp` using
  1096. [link foldr_start_with_parser `foldr_start_with_parser`]:
  1097. > using mult_exp3 = \
  1098. ...> foldr_start_with_parser< \
  1099. ...> sequence<int_token, one_of<times_token, divides_token>>, /* The parser applied repeatedly */ \
  1100. ...> int_token, /* The parser parsing the last number */ \
  1101. ...> boost::mpl::quote2<reverse_binary_op> /* The function called for every result */ \
  1102. ...> /* of applying the above parser */ \
  1103. ...> >;
  1104. [link getting_started_26 copy-paste friendly version]
  1105. It is almost the same as `mult_exp2`, but ...
  1106. * ... the parser applied repeatedly parses `<number> <operator>` elements
  1107. instead of `<operator> <number>` elements (what `mult_exp2` did).
  1108. * ... this version uses `reverse_binary_op` instead of `binary_op` as the
  1109. function that is called for every result of applying the above parser.
  1110. We can create a new version of `exp_parser` that uses `mult_exp3` instead of
  1111. `mult_exp2`:
  1112. > using exp_parser17 = \
  1113. ...> build_parser< \
  1114. ...> foldl_start_with_parser< \
  1115. ...> sequence<one_of<plus_token, minus_token>, mult_exp3>, \
  1116. ...> mult_exp3, \
  1117. ...> boost::mpl::quote2<binary_op> \
  1118. ...> > \
  1119. ...> >;
  1120. [link getting_started_27 copy-paste friendly version]
  1121. The only difference between `exp_parser17` and the previous version,
  1122. `exp_parser16` is that it uses the updated version of `mult_exp`. Let's try this
  1123. parser out:
  1124. > exp_parser17::apply<BOOST_METAPARSE_STRING("8 / 4 / 2")>::type
  1125. mpl_::integral_c<int, 4>
  1126. This version of the parser gives ['the other] possible result. The one you get
  1127. when division is right associative, which means that the above expression is
  1128. evaluated as `8 / (4 / 2)`. Here is a diagram showing how the
  1129. [link foldr_start_with_parser `foldr_start_with_parser`]-based solution works:
  1130. [$images/metaparse/tutorial_diag10.png [width 70%]]
  1131. To make it easier to compare the two solutions, here is a diagram showing the
  1132. two approaches side-by-side:
  1133. [$images/metaparse/tutorial_diag11.png [width 100%]]
  1134. As we have seen, the associativity of the operators can be controlled by
  1135. choosing between folding solutions. The folding solutions going from left to
  1136. right implement left associativity, while the solutions going from right to left
  1137. implement right associativity.
  1138. [note
  1139. Note that folding solutions going from left to right is implemented in a more
  1140. efficient way than folding from right to left. Therefore when both solutions
  1141. can be used you should prefer folding from left to right.
  1142. ]
  1143. [endsect]
  1144. [endsect]
  1145. [section 9. Dealing with unary operators]
  1146. [note Note that you can find everything that has been included and defined so far [link before_9 here].]
  1147. Our calculator language provides no direct support for negative numbers. To get
  1148. a negative number, we need to do a subtraction. For example to get the number
  1149. `-13` we need to evaluate the expression `0 - 13`.
  1150. We will implement `-` as a unary operator. Therefore the expression `-13` won't
  1151. be a ['negative number]. It will be the unary `-` operator applied on the number
  1152. `13`.
  1153. Since `-` is an operator, it might be used multiple times. So the expression
  1154. `---13` is also valid and gives the same result as `-13`. This means that any
  1155. number of `-` symbols are valid before a number.
  1156. Our parser can be extended to support the unary `-` operator by adding a new
  1157. layer to the list of precedence layers. This should have the lowest precedence,
  1158. which means that we should use this new layer where we have been using
  1159. `int_token`. Let's write a new parser:
  1160. > #include <boost/mpl/negate.hpp>
  1161. > using unary_exp1 = \
  1162. ...> foldr_start_with_parser< \
  1163. ...> minus_token, \
  1164. ...> int_token, \
  1165. ...> boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
  1166. ...> >;
  1167. [link getting_started_28 copy-paste friendly version]
  1168. We had to include `<boost/mpl/negate.hpp>` to get a
  1169. [link metafunction metafunction] we can negate a value with.
  1170. `unary_exp1` is implemented with right to left folding: it starts from the
  1171. number (parsed by `int_token`) and processes the `-` symbols one by one. The
  1172. function to be called for each `-` symbol is a lambda expression that negates
  1173. the number. So the number is negated for every `-` symbol.
  1174. We can implement a new version of `mult_exp` and `exp_parser`. They are the same
  1175. as `mult_exp2` and `exp_parser16`. The only difference is that they (directly
  1176. only `exp_parser18`) use `unary_exp1` instead of `int_token`.
  1177. > using mult_exp4 = \
  1178. ...> foldl_start_with_parser< \
  1179. ...> sequence<one_of<times_token, divides_token>, unary_exp1>, \
  1180. ...> unary_exp1, \
  1181. ...> boost::mpl::quote2<binary_op> \
  1182. ...> >;
  1183. > using exp_parser18 = \
  1184. ...> build_parser< \
  1185. ...> foldl_start_with_parser< \
  1186. ...> sequence<one_of<plus_token, minus_token>, mult_exp4>, \
  1187. ...> mult_exp4, \
  1188. ...> boost::mpl::quote2<binary_op> \
  1189. ...> > \
  1190. ...> >;
  1191. [link getting_started_29 copy-paste friendly version]
  1192. Let's try these new parsers out:
  1193. > exp_parser18::apply<BOOST_METAPARSE_STRING("---13")>::type
  1194. mpl_::integral_c<int, -13>
  1195. > exp_parser18::apply<BOOST_METAPARSE_STRING("13")>::type
  1196. mpl_::integral_c<int, 13>
  1197. [link getting_started_30 copy-paste friendly version]
  1198. It can deal with negative numbers correctly.
  1199. [endsect]
  1200. [section 10. Dealing with parens]
  1201. Our parsers already support the precedence of the different operators. Let's add
  1202. support for parens as well, so users can override the precedence rules when they
  1203. need to.
  1204. We can add a new parser for parsing (and evaluating) expressions in parens.
  1205. First we introduce tokens for parsing the `(` and `)` symbols:
  1206. > using lparen_token = token<lit_c<'('>>;
  1207. > using rparen_token = token<lit_c<')'>>;
  1208. [link getting_started_31 copy-paste friendly version]
  1209. A paren can contain an expression with any operators in it, so we add a parser
  1210. for parsing (and evaluating) an expression containing operators of the highest
  1211. precedence:
  1212. > using plus_exp1 = \
  1213. ...> foldl_start_with_parser< \
  1214. ...> sequence<one_of<plus_token, minus_token>, mult_exp4>, \
  1215. ...> mult_exp4, \
  1216. ...> boost::mpl::quote2<binary_op> \
  1217. ...> >;
  1218. [link getting_started_32 copy-paste friendly version]
  1219. This was just a refactoring of our last parser for the calculator language. We
  1220. can build the parser for our calculator language by using
  1221. [link build_parser `build_parser`]`<plus_exp1>` now. Let's write a parser for a
  1222. paren expression:
  1223. > using paren_exp1 = sequence<lparen_token, plus_exp1, rparen_token>;
  1224. This definition parses a left paren, then a complete expression followed by a
  1225. right paren. The result of parsing a paren expression is a `vector` of three
  1226. elements: the `(` character, the value of the expression and the `)` character.
  1227. We only need the value of the expression, which is the middle element. We could
  1228. wrap the whole thing with a [link transform `transform`] that gets the middle
  1229. element and throws the rest away, but we don't need to. This is such a common
  1230. pattern, that Metaparse provides [link middle_of `middle_of`] for this:
  1231. > #include <boost/metaparse/middle_of.hpp>
  1232. > using paren_exp2 = middle_of<lparen_token, plus_exp1, rparen_token>;
  1233. [link getting_started_33 copy-paste friendly version]
  1234. This implementation is almost the same as `paren_exp1`. The difference is that
  1235. the result of parsing will be the value of the wrapped expression (the result of
  1236. the `plus_exp1` parser).
  1237. Let's define a parser for a primary expression which is either a number or an
  1238. expression in parens:
  1239. > using primary_exp1 = one_of<int_token, paren_exp2>;
  1240. This parser accepts either a number using `int_token` or an expression in parens
  1241. using `paren_exp1`.
  1242. Everywhere, where one can write a number (parsed by `int_token`), one can write
  1243. a complete expression in parens as well. Our current parser implementation
  1244. parses `int_token`s in `unary_exp`, therefore we need to change that to use
  1245. `primary_exp` instead of `int_token`.
  1246. There is a problem here: this makes the definitions of our parsers ['recursive].
  1247. Think about it:
  1248. * `plus_exp` uses `mult_exp`
  1249. * `mult_exp` uses `unary_exp`
  1250. * `unary_exp` uses `primary_exp`
  1251. * `primary_exp` uses `paren_exp`
  1252. * `paren_exp` uses `plus_exp`
  1253. [note
  1254. Since we are versioning the different parser implementations in Metashell
  1255. (`paren_exp1`, `paren_exp2`, etc) you might try to define these recursive
  1256. parsers and it might seem to work for the first time. In that case, when you
  1257. later try creating a parser as part of a library (save your Metashell
  1258. environment to a file or re-implement the important/successful elements) you
  1259. face this issue.
  1260. ]
  1261. We have been using type aliases (`typedef` and `using`) for defining the
  1262. parsers. We can do it as long as their definition is not recursive. We can not
  1263. refer to a type alias until we have defined it and type aliases can not be
  1264. forward declared, so we can't find a point in the recursive cycle where we could
  1265. start defining things.
  1266. A solution for this is making one of the parsers a new class instead of a type
  1267. alias. Classes can be forward declared, therefore we can declare the class,
  1268. implement the rest of the parsers as they can refer to that class and then
  1269. define the class at the end.
  1270. Let's make `plus_exp` a class. So as a first step, let's forward declare it:
  1271. > struct plus_exp2;
  1272. Now we can write the rest of the parsers and they can refer to `plus_exp2`:
  1273. > using paren_exp3 = middle_of<lparen_token, plus_exp2, rparen_token>;
  1274. > using primary_exp2 = one_of<int_token, paren_exp2>;
  1275. > using unary_exp2 = \
  1276. ...> foldr_start_with_parser< \
  1277. ...> minus_token, \
  1278. ...> primary_exp2, \
  1279. ...> boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
  1280. ...> >;
  1281. > using mult_exp5 = \
  1282. ...> foldl_start_with_parser< \
  1283. ...> sequence<one_of<times_token, divides_token>, unary_exp2>, \
  1284. ...> unary_exp2, \
  1285. ...> boost::mpl::quote2<binary_op> \
  1286. ...> >;
  1287. [link getting_started_34 copy-paste friendly version]
  1288. There is nothing new in the definition of these parsers. They build up the
  1289. hierarchy we have worked out in the earlier sections of this tutorial. The only
  1290. element missing is `plus_exp2`:
  1291. > struct plus_exp2 : \
  1292. ...> foldl_start_with_parser< \
  1293. ...> sequence<one_of<plus_token, minus_token>, mult_exp5>, \
  1294. ...> mult_exp5, \
  1295. ...> boost::mpl::quote2<binary_op> \
  1296. ...> > {};
  1297. [link getting_started_35 copy-paste friendly version]
  1298. This definition makes use of inheritance instead of type aliasing. Now we can
  1299. write the parser for the calculator that supports parens as well:
  1300. > using exp_parser19 = build_parser<plus_exp2>;
  1301. Let's try this parser out:
  1302. > exp_parser19::apply<BOOST_METAPARSE_STRING("(1 + 2) * 3")>::type
  1303. mpl_::integral_c<int, 9>
  1304. Our parser accepts and can deal with parens in the expressions.
  1305. [endsect]
  1306. [#dealing_with_invalid_input]
  1307. [section 11. Dealing with invalid input]
  1308. So far we have been focusing on parsing valid user input. However, users of our
  1309. parsers will make mistakes and we should help them finding the source of the
  1310. problem. And we should make this process not too painful.
  1311. The major difficulty in error reporting is that we have no direct way of showing
  1312. error messages to the user. The parsers are template metaprograms. When they
  1313. detect that the input is invalid, they can make the compilation fail and the
  1314. compiler (running the metaprogram) display an error message. What we can do is
  1315. making those error messages short and contain all information about the parsing
  1316. error. We should make it easy to find this information in whatever the compiler
  1317. displays.
  1318. So let's try to parse some invalid expression and let's see what happens:
  1319. > exp_parser19::apply<BOOST_METAPARSE_STRING("hello")>::type
  1320. << compilation error >>
  1321. You will get a lot (if you have seen error messages coming from template
  1322. metaprograms you know: this is ['not] a lot.) of error messages. Take a closer
  1323. look. It contains this:
  1324. x__________________PARSING_FAILED__________________x<
  1325. 1, 1,
  1326. boost::metaparse::v1::error::literal_expected<'('>
  1327. >
  1328. You can see a formatted version above. There are no line breaks in the real
  1329. output. This is relatively easy to spot (thanks to the `____________` part) and
  1330. contains answers to the main questions one has when parsing fails:
  1331. * ['where] is the error? It is column `1` in line `1` (inside
  1332. [link BOOST_METAPARSE_STRING `BOOST_METAPARSE_STRING`]). This is the `1, 1`
  1333. part.
  1334. * ['what] is the problem? `literal_expected<'('>`. This is a bit misleading, as
  1335. it contains only a part of the problem. An open paren is not the only
  1336. acceptable token here, a number would also be fine. This misleading error
  1337. message is ['our] fault: ['we] (the parser authors) need to make the parsing
  1338. errors more descriptive.
  1339. [section 11.1. Improving the error messages]
  1340. So how can we improve the error messages? Let's look at what went wrong in the
  1341. previous case:
  1342. * The input was `hello`.
  1343. * `plus_exp2` tried to parse it.
  1344. * `plus_exp2` tried to parse it using `mult_exp5` (assuming that this is the
  1345. initial `mult_exp` in the list of `+` / `-` separated `mult_exp`s).
  1346. * so `mult_exp5` tried to parse it.
  1347. * `mult_exp5` tried to parse it using `unary_exp2` (assuming that this is the
  1348. initial `unary_exp` in the list of `*` / `/` separated `unary_exp`s).
  1349. * so `unary_exp2` tried to parse it.
  1350. * `unary_exp2` parsed all of the `-` symbols using `minus_token`. There were
  1351. none of them (the input started with an `h` character).
  1352. * so `unary_exp2` tried to parse it using `primary_exp2`.
  1353. * `primary_exp2` is: [link one_of `one_of`]`<int_token, paren_exp2>`. It tried
  1354. parsing the input with `int_token` (which failed) and then with `paren_exp2`
  1355. (which failed as well). So [link one_of `one_of`] could not parse the input
  1356. with any of the choices and therefore it failed as well. In such situations
  1357. `one_of` checks which parser made the most progress (consumed the most
  1358. characters of the input) before failing and assumes, that that is the parser
  1359. the user intended to use, thus it returns the error message coming from that
  1360. parser. In this example none of the parsers could make any progress, in which
  1361. case `one_of` returns the error coming from the last parser in the list. This
  1362. was `paren_exp2`, and it expects the expression to start with an open paren.
  1363. This is where the error message came from. The rest of the layers did not
  1364. change or improve this error message so this was the error message displayed
  1365. to the user.
  1366. We, the parser authors know: we expect a primary expression there. When
  1367. [link one_of `one_of`] fails, it means that none was found.
  1368. [endsect]
  1369. [section 11.2. Defining custom errors]
  1370. To be able to return custom error messages (like `missing_primary_expression`)
  1371. to the user, we need to define those error messages first. The error messages
  1372. are represented by classes with some requirements:
  1373. * It should have a static method called `get_value()` returning a `std::string`
  1374. containing the description of the error.
  1375. * It should be a [link metaprogramming_value template metaprogramming value].
  1376. These classes are called [link parsing_error_message parsing error message]s.
  1377. To make it easy to implement such classes and to make it difficult (if not
  1378. impossible) to forget to fulfill a requirement, Metaparse provides a macro for
  1379. defining these classes. To get this macro, include the following header:
  1380. > #include <boost/metaparse/define_error.hpp>
  1381. Let's define the [link parsing_error_message parsing error message]:
  1382. > BOOST_METAPARSE_DEFINE_ERROR(missing_primary_expression, "Missing primary expression");
  1383. This defines a class called `missing_primary_expression` representing this error
  1384. message. What we need to do is making our parser return this error message when
  1385. [link one_of `one_of`] fails.
  1386. Let's define `plus_exp` and `paren_exp` first. Their definition does not change:
  1387. > struct plus_exp3;
  1388. > using paren_exp4 = middle_of<lparen_token, plus_exp3, rparen_token>;
  1389. [link getting_started_36 copy-paste friendly version]
  1390. When the input contains no number (parsed by `int_token`) and no paren
  1391. expression (parsed by `paren_exp4`), we should return the
  1392. `missing_primary_expression` error message. We can do it by adding a third
  1393. parser to `one_of<int_token, paren_exp4, ...>` which always fails with this
  1394. error message. Metaparse provides [link fail `fail`] for this:
  1395. > #include <boost/metaparse/fail.hpp>
  1396. Now we can define the `primary_exp` parser using it:
  1397. > using primary_exp3 = one_of<int_token, paren_exp4, fail<missing_primary_expression>>;
  1398. It adds [link fail `fail`]`<missing_primary_expression>` to `one_of` as the
  1399. last element. Therefore if none of the "real" cases parse the input ['and] none
  1400. of them makes any progress before failing, the error message will be
  1401. `missing_primary_expression`.
  1402. We need to define the rest of the parsers. Their definition is the same as
  1403. before:
  1404. > using unary_exp3 = \
  1405. ...> foldr_start_with_parser< \
  1406. ...> minus_token, \
  1407. ...> primary_exp3, \
  1408. ...> boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
  1409. ...> >;
  1410. > using mult_exp6 = \
  1411. ...> foldl_start_with_parser< \
  1412. ...> sequence<one_of<times_token, divides_token>, unary_exp3>, \
  1413. ...> unary_exp3, \
  1414. ...> boost::mpl::quote2<binary_op> \
  1415. ...> >;
  1416. > struct plus_exp3 : \
  1417. ...> foldl_start_with_parser< \
  1418. ...> sequence<one_of<plus_token, minus_token>, mult_exp6>, \
  1419. ...> mult_exp6, \
  1420. ...> boost::mpl::quote2<binary_op> \
  1421. ...> > {};
  1422. > using exp_parser20 = build_parser<plus_exp3>;
  1423. [link getting_started_37 copy-paste friendly version]
  1424. We can try to give our new parser an invalid input:
  1425. > exp_parser20::apply<BOOST_METAPARSE_STRING("hello")>::type
  1426. << compilation error >>
  1427. ..... x__________________PARSING_FAILED__________________x<1, 1, missing_primary_expression> ....
  1428. << compilation error >>
  1429. The error message is now more specific to the calculator language. This covers
  1430. only one case, where the error messages can be improved. Other cases (eg.
  1431. missing closing parens, missing operators, etc) can be covered in a similar way.
  1432. [endsect]
  1433. [section 11.3. Missing closing parens]
  1434. Missing closing parens are common errors. Let's see how our parsers report them:
  1435. > exp_parser20::apply<BOOST_METAPARSE_STRING("(1+2")>::type
  1436. << compilation error >>
  1437. ..... x__________________PARSING_FAILED__________________x<1, 5, unpaired<1, 1, literal_expected<')'>>> ....
  1438. << compilation error >>
  1439. The parser could detect that there is a missing paren and the error report
  1440. points to the open paren which is not closed. This looks great, but we are not
  1441. done yet. Let's try a slightly more complex input:
  1442. > exp_parser20::apply<BOOST_METAPARSE_STRING("0+(1+2")>::type
  1443. mpl_::integral_c<int, 0>
  1444. This is getting strange now. We parse the `+ <mult_exp>` elements using
  1445. [link foldl_start_with_parser `foldl_start_with_parser`] (see the definition of
  1446. `plus_exp3`). [link foldl_start_with_parser `foldl_start_with_parser`] parses
  1447. the input as long as it can and stops when it fails to parse it. In the above
  1448. input, it parses `0` as the initial element and then it tries to parse the first
  1449. `+ <mult_exp>` element. But parsing the `<mult_exp>` part fails because of the
  1450. missing closing paren. So
  1451. [link foldl_start_with_parser `foldl_start_with_parser`] stops and ignores this
  1452. failing part of the input.
  1453. The result of the above is that we parse only the `0` part of the input, ignore
  1454. the "garbage" at the end and assume that the value of the expression is `0`.
  1455. This could be fixed by using [link entire_input `entire_input`]. Our parser
  1456. would reject the input (because of the "garbage" at the end), but the error
  1457. message would not be useful. So we take a different approach.
  1458. When [link foldl_start_with_parser `foldl_start_with_parser`] stops, we should
  1459. check if there is an extra broken `+ <mult_exp>` there or not. When there is, we
  1460. should report what is wrong with that broken `+ <mult_exp>` (eg. a missing
  1461. closing paren). Metaparse provides [link fail_at_first_char_expected
  1462. `fail_at_first_char_expected`] to implement such validations.
  1463. [link fail_at_first_char_expected `fail_at_first_char_expected`]`<parser>`
  1464. checks how `parser` fails to parse the input: when it fails right at the first
  1465. character, [link fail_at_first_char_expected `fail_at_first_char_expected`]
  1466. assumes that there is no garbage and accepts the input. When `parser` consumes
  1467. characters from the input before failing,
  1468. [link fail_at_first_char_expected `fail_at_first_char_expected`] assumes that
  1469. there is a broken expression and propagates the error. It can be used the
  1470. following way:
  1471. > #include <boost/metaparse/fail_at_first_char_expected.hpp>
  1472. > #include <boost/metaparse/first_of.hpp>
  1473. > struct plus_exp4 : \
  1474. ...> first_of< \
  1475. ...> foldl_start_with_parser< \
  1476. ...> sequence<one_of<plus_token, minus_token>, mult_exp6>, \
  1477. ...> mult_exp6, \
  1478. ...> boost::mpl::quote2<binary_op> \
  1479. ...> >, \
  1480. ...> fail_at_first_char_expected< \
  1481. ...> sequence<one_of<plus_token, minus_token>, mult_exp6> \
  1482. ...> > \
  1483. ...> > {};
  1484. > using exp_parser21 = build_parser<plus_exp4>;
  1485. [link getting_started_38 copy-paste friendly version]
  1486. [link first_of `first_of`] is similar to [link middle_of `middle_of`], but
  1487. keeps the result of the first element, not the middle one. We use it to keep the
  1488. "real" result (the result of
  1489. [link foldl_start_with_parser `foldl_start_with_parser`]) and to throw the dummy
  1490. result coming from
  1491. [link fail_at_first_char_expected `fail_at_first_char_expected`] away when
  1492. there is no broken expression at the end. [link first_of `first_of`] propagates
  1493. any error coming from
  1494. [link fail_at_first_char_expected `fail_at_first_char_expected`].
  1495. Let's try this new expression parser out with a missing closing paren:
  1496. > exp_parser21::apply<BOOST_METAPARSE_STRING("0+(1+2")>::type
  1497. << compilation error >>
  1498. ..... x__________________PARSING_FAILED__________________x<1, 7, unpaired<1, 3, literal_expected<')'>>> ....
  1499. << compilation error >>
  1500. This works as expected now: it tells us that there is a missing paren and it
  1501. points us the open paren which is not closed.
  1502. [section 11.3.1. Simplifying the parser]
  1503. Our parser provides useful error messages for missing closing parens, however,
  1504. the implementation of the parser (`plus_exp4`) is long and repetitive: it
  1505. contains the parser for the repeated element
  1506. ([link sequence `sequence`]`<`[link one_of `one_of`]`<plus_token, minus_token>, mult_exp6>`) twice, and that is not ideal.
  1507. `plus_exp4` uses [link foldl_start_with_parser `foldl_start_with_parser`] to
  1508. implement repetition. Metaparse provides
  1509. [link foldl_reject_incomplete_start_with_parser `foldl_reject_incomplete_start_with_parser`]
  1510. which does the same we did with [link first_of `first_of`],
  1511. [link foldl_start_with_parser `foldl_start_with_parser`] and
  1512. [link fail_at_first_char_expected `fail_at_first_char_expected`] together:
  1513. > #include <boost/metaparse/foldl_reject_incomplete_start_with_parser.hpp>
  1514. > struct plus_exp5 : \
  1515. ...> foldl_reject_incomplete_start_with_parser< \
  1516. ...> sequence<one_of<plus_token, minus_token>, mult_exp6>, \
  1517. ...> mult_exp6, \
  1518. ...> boost::mpl::quote2<binary_op> \
  1519. ...> > {};
  1520. > using exp_parser22 = build_parser<plus_exp5>;
  1521. [link getting_started_39 copy-paste friendly version]
  1522. It parses the input using
  1523. [link sequence `sequence`]`<`[link one_of `one_of`]`<plus_token, minus_token>, mult_exp6>`)
  1524. repeatedly. When it fails,
  1525. [link foldl_reject_incomplete_start_with_parser `foldl_reject_incomplete_start_with_parser`]
  1526. checks if it consumed any character before failing (the same as what
  1527. [link fail_at_first_char_expected `fail_at_first_char_expected`] does), and if
  1528. yes, then
  1529. [link foldl_reject_incomplete_start_with_parser `foldl_reject_incomplete_start_with_parser`]
  1530. fails.
  1531. This makes the implementation of the repetition with advanced error reporting
  1532. simpler. Let's try it out:
  1533. > exp_parser22::apply<BOOST_METAPARSE_STRING("0+(1+2")>::type
  1534. << compilation error >>
  1535. ..... x__________________PARSING_FAILED__________________x<1, 7, unpaired<1, 3, literal_expected<')'>>> ....
  1536. << compilation error >>
  1537. Note that other folding parsers have their `f` versions as well (eg.
  1538. [link foldr_reject_incomplete `foldr_reject_incomplete`],
  1539. [link foldl_reject_incomplete1 `foldl_reject_incomplete1`], etc).
  1540. [endsect]
  1541. [section 11.3.2. Using `foldl_reject_incomplete_start_with_parser` at other places as well]
  1542. We have replaced one [link foldl_start_with_parser `foldl_start_with_parser`]
  1543. with
  1544. [link foldl_reject_incomplete_start_with_parser `foldl_reject_incomplete_start_with_parser`].
  1545. Other layers (`mult_exp`, `unary_exp`, etc) use folding as well. Let's use it at
  1546. all layers:
  1547. > struct plus_exp6;
  1548. > using paren_exp5 = middle_of<lparen_token, plus_exp6, rparen_token>;
  1549. > using primary_exp4 = one_of<int_token, paren_exp5, fail<missing_primary_expression>>;
  1550. > using unary_exp4 = \
  1551. ...> foldr_start_with_parser< \
  1552. ...> minus_token, \
  1553. ...> primary_exp4, \
  1554. ...> boost::mpl::lambda<boost::mpl::negate<boost::mpl::_1>>::type \
  1555. ...> >;
  1556. > using mult_exp7 = \
  1557. ...> foldl_reject_incomplete_start_with_parser< \
  1558. ...> sequence<one_of<times_token, divides_token>, unary_exp4>, \
  1559. ...> unary_exp4, \
  1560. ...> boost::mpl::quote2<binary_op> \
  1561. ...> >;
  1562. > struct plus_exp6 : \
  1563. ...> foldl_reject_incomplete_start_with_parser< \
  1564. ...> sequence<one_of<plus_token, minus_token>, mult_exp7>, \
  1565. ...> mult_exp7, \
  1566. ...> boost::mpl::quote2<binary_op> \
  1567. ...> > {};
  1568. > using exp_parser23 = build_parser<plus_exp6>;
  1569. [link getting_started_40 copy-paste friendly version]
  1570. [note
  1571. Note that `unary_exp4` uses
  1572. [link foldr_start_with_parser `foldr_start_with_parser`] instead of
  1573. `foldr_reject_incomplete_start_with_parser`. The reason behind it is that there
  1574. is no `foldr_reject_incomplete_start_with_parser`.
  1575. [link foldr_start_with_parser `foldr_start_with_parser`] applies the
  1576. `primary_exp4` parser when `minus_token` does not accept the input any more.
  1577. Therefore, it is supposed to catch the errors of incomplete expressions after
  1578. the repetition.
  1579. ]
  1580. Let's try different invalid expressions:
  1581. > exp_parser23::apply<BOOST_METAPARSE_STRING("1+(2*")>::type
  1582. << compilation error >>
  1583. ..... x__________________PARSING_FAILED__________________x<1, 6, missing_primary_expression> ....
  1584. << compilation error >>
  1585. > exp_parser23::apply<BOOST_METAPARSE_STRING("1+(2*3")>::type
  1586. << compilation error >>
  1587. ..... x__________________PARSING_FAILED__________________x<1, 7, unpaired<1, 3, literal_expected<')'>>> ....
  1588. << compilation error >>
  1589. [endsect]
  1590. [endsect]
  1591. [endsect]
  1592. [section 12. Summary]
  1593. This tutorial showed you how to build a parser for a calculator language. Now
  1594. that you understand how to do this, you should be able to use the same
  1595. techniques and building blocks presented here to build a parser for your own
  1596. language. You should start building the parser and once you face a problem (eg.
  1597. you need to add parens or you need better error messages) you can always return
  1598. to this tutorial and read the section showing you how to deal with those
  1599. situations.
  1600. [endsect]
  1601. [section Copy-paste friendly code examples]
  1602. [include getting_started_0.qbk]
  1603. [include getting_started_1.qbk]
  1604. [include getting_started_2.qbk]
  1605. [include getting_started_3.qbk]
  1606. [include getting_started_4.qbk]
  1607. [include getting_started_5.qbk]
  1608. [include getting_started_6.qbk]
  1609. [include getting_started_7.qbk]
  1610. [include getting_started_8.qbk]
  1611. [include getting_started_9.qbk]
  1612. [include getting_started_10.qbk]
  1613. [include getting_started_11.qbk]
  1614. [include getting_started_12.qbk]
  1615. [include getting_started_13.qbk]
  1616. [include getting_started_14.qbk]
  1617. [include getting_started_15.qbk]
  1618. [include getting_started_16.qbk]
  1619. [include getting_started_17.qbk]
  1620. [include getting_started_18.qbk]
  1621. [include getting_started_19.qbk]
  1622. [include getting_started_20.qbk]
  1623. [include getting_started_21.qbk]
  1624. [include getting_started_22.qbk]
  1625. [include getting_started_23.qbk]
  1626. [include getting_started_24.qbk]
  1627. [include getting_started_25.qbk]
  1628. [include getting_started_26.qbk]
  1629. [include getting_started_27.qbk]
  1630. [include getting_started_28.qbk]
  1631. [include getting_started_29.qbk]
  1632. [include getting_started_30.qbk]
  1633. [include getting_started_31.qbk]
  1634. [include getting_started_32.qbk]
  1635. [include getting_started_33.qbk]
  1636. [include getting_started_34.qbk]
  1637. [include getting_started_35.qbk]
  1638. [include getting_started_36.qbk]
  1639. [include getting_started_37.qbk]
  1640. [include getting_started_38.qbk]
  1641. [include getting_started_39.qbk]
  1642. [include getting_started_40.qbk]
  1643. [endsect]
  1644. [section Definitions before each section]
  1645. [include before_3.qbk]
  1646. [include before_3_1.qbk]
  1647. [include before_3_2.qbk]
  1648. [include before_3_3.qbk]
  1649. [include before_4.qbk]
  1650. [include before_4_1.qbk]
  1651. [include before_4_2.qbk]
  1652. [include before_5.qbk]
  1653. [include before_5_1.qbk]
  1654. [include before_5_2.qbk]
  1655. [include before_5_2_1.qbk]
  1656. [include before_5_2_2.qbk]
  1657. [include before_5_2_3.qbk]
  1658. [include before_5_2_4.qbk]
  1659. [include before_6.qbk]
  1660. [include before_6_1.qbk]
  1661. [include before_6_2.qbk]
  1662. [include before_7.qbk]
  1663. [include before_7_1.qbk]
  1664. [include before_7_2.qbk]
  1665. [include before_8.qbk]
  1666. [include before_8_1.qbk]
  1667. [include before_8_2.qbk]
  1668. [include before_9.qbk]
  1669. [include before_10.qbk]
  1670. [include before_11.qbk]
  1671. [include before_11_1.qbk]
  1672. [include before_11_2.qbk]
  1673. [include before_11_3.qbk]
  1674. [include before_11_3_1.qbk]
  1675. [include before_11_3_2.qbk]
  1676. [include before_12.qbk]
  1677. [endsect]
  1678. [endsect]