annotation.html 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Annotations - Decorating the ASTs</title>
  5. <link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
  6. <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  7. <link rel="home" href="../../index.html" title="Spirit X3 3.0.4">
  8. <link rel="up" href="../tutorials.html" title="Tutorials">
  9. <link rel="prev" href="minimal.html" title="X3 Program Structure">
  10. <link rel="next" href="rexpr.html" title="RExpressions - Recursive ASTs!">
  11. </head>
  12. <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  13. <table cellpadding="2" width="100%"><tr>
  14. <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
  15. <td align="center"><a href="../../../../../../../index.html">Home</a></td>
  16. <td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
  17. <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
  18. <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
  19. <td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
  20. </tr></table>
  21. <hr>
  22. <div class="spirit-nav">
  23. <a accesskey="p" href="minimal.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorials.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rexpr.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
  24. </div>
  25. <div class="section">
  26. <div class="titlepage"><div><div><h3 class="title">
  27. <a name="spirit_x3.tutorials.annotation"></a><a class="link" href="annotation.html" title="Annotations - Decorating the ASTs">Annotations - Decorating
  28. the ASTs</a>
  29. </h3></div></div></div>
  30. <p>
  31. As a prerequisite in understanding this tutorial, please review the previous
  32. <a class="link" href="employee.html" title="Employee - Parsing into structs">employee example</a>. This
  33. example builds on top of that example.
  34. </p>
  35. <p>
  36. Stop and think about it... We're actually generating ASTs (abstract syntax
  37. trees) in our previoius examples. We parsed a single structure and generated
  38. an in-memory representation of it in the form of a struct: the struct employee.
  39. If we changed the implementation to parse one or more employees, the result
  40. would be a std::vector&lt;employee&gt;. We can go on and add more hierarchy:
  41. teams, departments, corporations, etc. We can have an AST representation
  42. of it all.
  43. </p>
  44. <p>
  45. This example shows how to annotate the AST with the iterator positions for
  46. access to the source code when post processing using a client supplied <code class="computeroutput"><span class="identifier">on_success</span></code> handler. The example will show
  47. how to get the position in input source stream that corresponds to a given
  48. element in the AST.
  49. </p>
  50. <p>
  51. In addition, This example also shows how to "inject" client data,
  52. using the "with" directive, that the <code class="computeroutput"><span class="identifier">on_success</span></code>
  53. handler can access as it is called within the parse traversal through the
  54. parser's context.
  55. </p>
  56. <p>
  57. The full cpp file for this example can be found here: <a href="../../../../../example/x3/annotation.cpp" target="_top">annotation.cpp</a>
  58. </p>
  59. <h5>
  60. <a name="spirit_x3.tutorials.annotation.h0"></a>
  61. <span class="phrase"><a name="spirit_x3.tutorials.annotation.the_ast"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.the_ast">The
  62. AST</a>
  63. </h5>
  64. <p>
  65. First, we'll update our previous employee struct, this time separating the
  66. person into its own struct. So now, we have two structs, the <code class="computeroutput"><span class="identifier">person</span></code> and the <code class="computeroutput"><span class="identifier">employee</span></code>.
  67. Take note too that we now inherit <code class="computeroutput"><span class="identifier">person</span></code>
  68. and <code class="computeroutput"><span class="identifier">employee</span></code> from <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span></code>
  69. which provides positional information that we can use to tell the AST's position
  70. in the input stream anytime.
  71. </p>
  72. <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">client</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">ast</span>
  73. <span class="special">{</span>
  74. <span class="keyword">struct</span> <span class="identifier">person</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span>
  75. <span class="special">{</span>
  76. <span class="identifier">person</span><span class="special">(</span>
  77. <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">first_name</span> <span class="special">=</span> <span class="string">""</span>
  78. <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">last_name</span> <span class="special">=</span> <span class="string">""</span>
  79. <span class="special">)</span>
  80. <span class="special">:</span> <span class="identifier">first_name</span><span class="special">(</span><span class="identifier">first_name</span><span class="special">)</span>
  81. <span class="special">,</span> <span class="identifier">last_name</span><span class="special">(</span><span class="identifier">last_name</span><span class="special">)</span>
  82. <span class="special">{}</span>
  83. <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">first_name</span><span class="special">,</span> <span class="identifier">last_name</span><span class="special">;</span>
  84. <span class="special">};</span>
  85. <span class="keyword">struct</span> <span class="identifier">employee</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span>
  86. <span class="special">{</span>
  87. <span class="keyword">int</span> <span class="identifier">age</span><span class="special">;</span>
  88. <span class="identifier">person</span> <span class="identifier">who</span><span class="special">;</span>
  89. <span class="keyword">double</span> <span class="identifier">salary</span><span class="special">;</span>
  90. <span class="special">};</span>
  91. <span class="special">}}</span>
  92. </pre>
  93. <p>
  94. Like before, we need to tell <a href="../../../../../../../libs/fusion/doc/html/index.html" target="_top">Boost.Fusion</a>
  95. about our structs to make them first-class fusion citizens that the grammar
  96. can utilize:
  97. </p>
  98. <pre class="programlisting"><span class="identifier">BOOST_FUSION_ADAPT_STRUCT</span><span class="special">(</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">person</span><span class="special">,</span>
  99. <span class="identifier">first_name</span><span class="special">,</span> <span class="identifier">last_name</span>
  100. <span class="special">)</span>
  101. <span class="identifier">BOOST_FUSION_ADAPT_STRUCT</span><span class="special">(</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">,</span>
  102. <span class="identifier">age</span><span class="special">,</span> <span class="identifier">who</span><span class="special">,</span> <span class="identifier">salary</span>
  103. <span class="special">)</span>
  104. </pre>
  105. <h5>
  106. <a name="spirit_x3.tutorials.annotation.h1"></a>
  107. <span class="phrase"><a name="spirit_x3.tutorials.annotation.x3__position_cache"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.x3__position_cache">x3::position_cache</a>
  108. </h5>
  109. <p>
  110. Before we proceed, let me introduce a helper class called the <code class="computeroutput"><span class="identifier">position_cache</span></code>. It is a simple class that
  111. collects iterator ranges that point to where each element in the AST are
  112. located in the input stream. Given an AST, you can query the position_cache
  113. about AST's position. For example:
  114. </p>
  115. <pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">positions</span><span class="special">.</span><span class="identifier">position_of</span><span class="special">(</span><span class="identifier">my_ast</span><span class="special">);</span>
  116. </pre>
  117. <p>
  118. Where <code class="computeroutput"><span class="identifier">my_ast</span></code> is the AST,
  119. <code class="computeroutput"><span class="identifier">positions</span></code> and is the <code class="computeroutput"><span class="identifier">position_cache</span></code>, <code class="computeroutput"><span class="identifier">position_of</span></code>
  120. returns an iterator range that points to the start and end (<code class="computeroutput"><span class="identifier">pos</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">pos</span><span class="special">.</span><span class="identifier">end</span><span class="special">()</span></code>)
  121. positions where the AST was parsed from. <code class="computeroutput"><span class="identifier">positions</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">positions</span><span class="special">.</span><span class="identifier">end</span><span class="special">()</span></code>
  122. points to the start and end of the entire input stream.
  123. </p>
  124. <h5>
  125. <a name="spirit_x3.tutorials.annotation.h2"></a>
  126. <span class="phrase"><a name="spirit_x3.tutorials.annotation.on_success"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.on_success">on_success</a>
  127. </h5>
  128. <p>
  129. The <code class="computeroutput"><span class="identifier">on_success</span></code> gives you
  130. everything you want from semantic actions without the visual clutter. Declarative
  131. code can and should be free from imperative code. <code class="computeroutput"><span class="identifier">on_success</span></code>
  132. as a concept and mechanism is an important departure from how things are
  133. done in Spirit's previous version: Qi.
  134. </p>
  135. <p>
  136. As demonstrated in the previous <a class="link" href="employee.html" title="Employee - Parsing into structs">employee
  137. example</a>, the preferred way to extract data from an input source is
  138. by having the parser collect the data for us into C++ structs as it traverses
  139. the input stream. Ideally, Spirit X3 grammars are fully attributed and declared
  140. in such a way that you do not have to add any imperative code and there should
  141. be no need for semantic actions at all. The parser simply works as declared
  142. and you get your data back as a result.
  143. </p>
  144. <p>
  145. However, there are certain cases where there's no way to avoid introducing
  146. imperative code. But semantic actions mess up our clean declarative grammars.
  147. If we care to keep our code clean, <code class="computeroutput"><span class="identifier">on_success</span></code>
  148. handlers are alternative callback hooks to client code that are executed
  149. by the parser after a successful parse without polluting the grammar. Like
  150. semantic actions, <code class="computeroutput"><span class="identifier">on_success</span></code>
  151. handlers have access to the AST, the iterators, and context. But, unlike
  152. semantic actions, <code class="computeroutput"><span class="identifier">on_success</span></code>
  153. handlers are cleanly separated from the actual grammar.
  154. </p>
  155. <h5>
  156. <a name="spirit_x3.tutorials.annotation.h3"></a>
  157. <span class="phrase"><a name="spirit_x3.tutorials.annotation.annotation_handler"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.annotation_handler">Annotation
  158. Handler</a>
  159. </h5>
  160. <p>
  161. As discussed, we annotate the AST with its position in the input stream with
  162. our <code class="computeroutput"><span class="identifier">on_success</span></code> handler:
  163. </p>
  164. <pre class="programlisting"><span class="comment">// tag used to get the position cache from the context</span>
  165. <span class="keyword">struct</span> <span class="identifier">position_cache_tag</span><span class="special">;</span>
  166. <span class="keyword">struct</span> <span class="identifier">annotate_position</span>
  167. <span class="special">{</span>
  168. <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Context</span><span class="special">&gt;</span>
  169. <span class="keyword">inline</span> <span class="keyword">void</span> <span class="identifier">on_success</span><span class="special">(</span><span class="identifier">Iterator</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">Iterator</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">last</span>
  170. <span class="special">,</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">ast</span><span class="special">,</span> <span class="identifier">Context</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">context</span><span class="special">)</span>
  171. <span class="special">{</span>
  172. <span class="keyword">auto</span><span class="special">&amp;</span> <span class="identifier">position_cache</span> <span class="special">=</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span><span class="identifier">position_cache_tag</span><span class="special">&gt;(</span><span class="identifier">context</span><span class="special">).</span><span class="identifier">get</span><span class="special">();</span>
  173. <span class="identifier">position_cache</span><span class="special">.</span><span class="identifier">annotate</span><span class="special">(</span><span class="identifier">ast</span><span class="special">,</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">last</span><span class="special">);</span>
  174. <span class="special">}</span>
  175. <span class="special">};</span>
  176. </pre>
  177. <p>
  178. <code class="computeroutput"><span class="identifier">position_cache_tag</span></code> is a special
  179. tag we will use to get a reference to the actual <code class="computeroutput"><span class="identifier">position_cache</span></code>,
  180. client data that we will inject at very start, when we call parse. More on
  181. that later.
  182. </p>
  183. <p>
  184. Our <code class="computeroutput"><span class="identifier">on_success</span></code> handler gets
  185. a reference to the actual <code class="computeroutput"><span class="identifier">position_cache</span></code>
  186. and calls its <code class="computeroutput"><span class="identifier">annotate</span></code> member
  187. function, passing in the AST and the iterators. <code class="computeroutput"><span class="identifier">position_cache</span><span class="special">.</span><span class="identifier">annotate</span><span class="special">(</span><span class="identifier">ast</span><span class="special">,</span>
  188. <span class="identifier">first</span><span class="special">,</span>
  189. <span class="identifier">last</span><span class="special">)</span></code>
  190. annotates the AST with information required by <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_tagged</span></code>.
  191. </p>
  192. <h5>
  193. <a name="spirit_x3.tutorials.annotation.h4"></a>
  194. <span class="phrase"><a name="spirit_x3.tutorials.annotation.the_parser"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.the_parser">The
  195. Parser</a>
  196. </h5>
  197. <p>
  198. Now we'll write a parser for our employee. To simplify, inputs will be of
  199. the form:
  200. </p>
  201. <pre class="programlisting"><span class="special">{</span> <span class="identifier">age</span><span class="special">,</span> <span class="string">"forename"</span><span class="special">,</span> <span class="string">"surname"</span><span class="special">,</span> <span class="identifier">salary</span> <span class="special">}</span>
  202. </pre>
  203. <p>
  204. <a name="__tutorial_annotated_employee_parser__"></a>Here we go:
  205. </p>
  206. <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">parser</span>
  207. <span class="special">{</span>
  208. <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">int_</span><span class="special">;</span>
  209. <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">double_</span><span class="special">;</span>
  210. <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">;</span>
  211. <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span>
  212. <span class="keyword">struct</span> <span class="identifier">quoted_string_class</span><span class="special">;</span>
  213. <span class="keyword">struct</span> <span class="identifier">person_class</span><span class="special">;</span>
  214. <span class="keyword">struct</span> <span class="identifier">employee_class</span><span class="special">;</span>
  215. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">quoted_string_class</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">quoted_string</span> <span class="special">=</span> <span class="string">"quoted_string"</span><span class="special">;</span>
  216. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">person_class</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">person</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">person</span> <span class="special">=</span> <span class="string">"person"</span><span class="special">;</span>
  217. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">employee_class</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">employee</span> <span class="special">=</span> <span class="string">"employee"</span><span class="special">;</span>
  218. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">quoted_string_def</span> <span class="special">=</span> <span class="identifier">lexeme</span><span class="special">[</span><span class="char">'"'</span> <span class="special">&gt;&gt;</span> <span class="special">+(</span><span class="identifier">char_</span> <span class="special">-</span> <span class="char">'"'</span><span class="special">)</span> <span class="special">&gt;&gt;</span> <span class="char">'"'</span><span class="special">];</span>
  219. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">person_def</span> <span class="special">=</span> <span class="identifier">quoted_string</span> <span class="special">&gt;&gt;</span> <span class="char">','</span> <span class="special">&gt;&gt;</span> <span class="identifier">quoted_string</span><span class="special">;</span>
  220. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">employee_def</span> <span class="special">=</span>
  221. <span class="char">'{'</span>
  222. <span class="special">&gt;&gt;</span> <span class="identifier">int_</span> <span class="special">&gt;&gt;</span> <span class="char">','</span>
  223. <span class="special">&gt;&gt;</span> <span class="identifier">person</span> <span class="special">&gt;&gt;</span> <span class="char">','</span>
  224. <span class="special">&gt;&gt;</span> <span class="identifier">double_</span>
  225. <span class="special">&gt;&gt;</span> <span class="char">'}'</span>
  226. <span class="special">;</span>
  227. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">employees</span> <span class="special">=</span> <span class="identifier">employee</span> <span class="special">&gt;&gt;</span> <span class="special">*(</span><span class="char">','</span> <span class="special">&gt;&gt;</span> <span class="identifier">employee</span><span class="special">);</span>
  228. <span class="identifier">BOOST_SPIRIT_DEFINE</span><span class="special">(</span><span class="identifier">quoted_string</span><span class="special">,</span> <span class="identifier">person</span><span class="special">,</span> <span class="identifier">employee</span><span class="special">);</span>
  229. <span class="special">}</span>
  230. </pre>
  231. <h5>
  232. <a name="spirit_x3.tutorials.annotation.h5"></a>
  233. <span class="phrase"><a name="spirit_x3.tutorials.annotation.rule_declarations"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.rule_declarations">Rule
  234. Declarations</a>
  235. </h5>
  236. <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">quoted_string_class</span><span class="special">;</span>
  237. <span class="keyword">struct</span> <span class="identifier">person_class</span><span class="special">;</span>
  238. <span class="keyword">struct</span> <span class="identifier">employee_class</span><span class="special">;</span>
  239. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">quoted_string_class</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">quoted_string</span> <span class="special">=</span> <span class="string">"quoted_string"</span><span class="special">;</span>
  240. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">person_class</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">person</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">person</span> <span class="special">=</span> <span class="string">"person"</span><span class="special">;</span>
  241. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="identifier">employee_class</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="keyword">const</span> <span class="identifier">employee</span> <span class="special">=</span> <span class="string">"employee"</span><span class="special">;</span>
  242. </pre>
  243. <p>
  244. Go back and review the original <a class="link" href="employee.html#__tutorial_employee_parser__">employee
  245. parser</a>. What has changed?
  246. </p>
  247. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  248. <li class="listitem">
  249. We split the single employee rule into three smaller rules: <code class="computeroutput"><span class="identifier">quoted_string</span></code>, <code class="computeroutput"><span class="identifier">person</span></code>
  250. and <code class="computeroutput"><span class="identifier">employee</span></code>.
  251. </li>
  252. <li class="listitem">
  253. We're using forward declared rule classes: <code class="computeroutput"><span class="identifier">quoted_string_class</span></code>,
  254. <code class="computeroutput"><span class="identifier">person_class</span></code>, and <code class="computeroutput"><span class="identifier">employee_class</span></code>.
  255. </li>
  256. </ul></div>
  257. <h5>
  258. <a name="spirit_x3.tutorials.annotation.h6"></a>
  259. <span class="phrase"><a name="spirit_x3.tutorials.annotation.rule_classes"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.rule_classes">Rule
  260. Classes</a>
  261. </h5>
  262. <p>
  263. Like before, in this example, the rule classes, <code class="computeroutput"><span class="identifier">quoted_string_class</span></code>,
  264. <code class="computeroutput"><span class="identifier">person_class</span></code>, and <code class="computeroutput"><span class="identifier">employee_class</span></code> provide statically known
  265. IDs for the rules required by X3 to perform its tasks. In addition to that,
  266. the rule class can also be extended to have some user-defined customization
  267. hooks that are called:
  268. </p>
  269. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  270. <li class="listitem">
  271. On success: After a rule sucessfully parses an input.
  272. </li>
  273. <li class="listitem">
  274. On Error: After a rule fails to parse.
  275. </li>
  276. </ul></div>
  277. <p>
  278. By subclassing the rule class from a client supplied handler such as our
  279. <code class="computeroutput"><span class="identifier">annotate_position</span></code> handler
  280. above:
  281. </p>
  282. <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">person_class</span> <span class="special">:</span> <span class="identifier">annotate_position</span> <span class="special">{};</span>
  283. <span class="keyword">struct</span> <span class="identifier">employee_class</span> <span class="special">:</span> <span class="identifier">annotate_position</span> <span class="special">{};</span>
  284. </pre>
  285. <p>
  286. The code above tells X3 to check the rule class if it has an <code class="computeroutput"><span class="identifier">on_success</span></code> or <code class="computeroutput"><span class="identifier">on_error</span></code>
  287. member functions and appropriately calls them on such events.
  288. </p>
  289. <a name="__tutorial_with_directive__"></a><h5>
  290. <a name="spirit_x3.tutorials.annotation.h7"></a>
  291. <span class="phrase"><a name="spirit_x3.tutorials.annotation.the_with_directive"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.the_with_directive">The
  292. with Directive</a>
  293. </h5>
  294. <p>
  295. For any parser <code class="computeroutput"><span class="identifier">p</span></code>, one can
  296. inject supplementary data that semantic actions and handlers can access later
  297. on when they are called. The general syntax is:
  298. </p>
  299. <pre class="programlisting"><span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">tag</span><span class="special">&gt;(</span><span class="identifier">data</span><span class="special">)[</span><span class="identifier">p</span><span class="special">]</span>
  300. </pre>
  301. <p>
  302. For our particular example, we use to inject the <code class="computeroutput"><span class="identifier">position_cache</span></code>
  303. into the parse for our <code class="computeroutput"><span class="identifier">annotate_position</span></code>
  304. on_success handler to have access to:
  305. </p>
  306. <pre class="programlisting"><span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span>
  307. <span class="comment">// we pass our position_cache to the parser so we can access</span>
  308. <span class="comment">// it later in our on_sucess handlers</span>
  309. <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">position_cache_tag</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">positions</span><span class="special">))</span>
  310. <span class="special">[</span>
  311. <span class="identifier">employees</span>
  312. <span class="special">];</span>
  313. </pre>
  314. <p>
  315. Typically this is done just before calling <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">parse</span></code>
  316. or <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">phrase_parse</span></code>. <code class="computeroutput"><span class="identifier">with</span></code>
  317. is a very lightwight operation. It is possible to inject as much data as
  318. you want, even multiple <code class="computeroutput"><span class="identifier">with</span></code>
  319. directives:
  320. </p>
  321. <pre class="programlisting"><span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">tag1</span><span class="special">&gt;(</span><span class="identifier">data1</span><span class="special">)</span>
  322. <span class="special">[</span>
  323. <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">tag2</span><span class="special">&gt;(</span><span class="identifier">data2</span><span class="special">)[</span><span class="identifier">p</span><span class="special">]</span>
  324. <span class="special">]</span>
  325. </pre>
  326. <p>
  327. Multiple <code class="computeroutput"><span class="identifier">with</span></code> directives
  328. can (perhaps not obviously) be injected from outside the called function.
  329. Here's an outline:
  330. </p>
  331. <pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Parser</span><span class="special">&gt;</span>
  332. <span class="keyword">void</span> <span class="identifier">bar</span><span class="special">(</span><span class="identifier">Parser</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">p</span><span class="special">)</span>
  333. <span class="special">{</span>
  334. <span class="comment">// Inject data2</span>
  335. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span> <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">tag2</span><span class="special">&gt;(</span><span class="identifier">data2</span><span class="special">)[</span><span class="identifier">p</span><span class="special">];</span>
  336. <span class="identifier">x3</span><span class="special">::</span><span class="identifier">parse</span><span class="special">(</span><span class="identifier">first</span><span class="special">,</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">parser</span><span class="special">);</span>
  337. <span class="special">}</span>
  338. <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
  339. <span class="special">{</span>
  340. <span class="comment">// Inject data1</span>
  341. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span> <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">tag1</span><span class="special">&gt;(</span><span class="identifier">data1</span><span class="special">)[</span><span class="identifier">my_parser</span><span class="special">];</span>
  342. <span class="identifier">bar</span><span class="special">(</span><span class="identifier">p</span><span class="special">);</span>
  343. <span class="special">}</span>
  344. </pre>
  345. <h5>
  346. <a name="spirit_x3.tutorials.annotation.h8"></a>
  347. <span class="phrase"><a name="spirit_x3.tutorials.annotation.let_s_parse"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.let_s_parse">Let's
  348. Parse</a>
  349. </h5>
  350. <p>
  351. Now we have the complete parse mechanism with support for annotations:
  352. </p>
  353. <pre class="programlisting"><span class="keyword">using</span> <span class="identifier">iterator_type</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">::</span><span class="identifier">const_iterator</span><span class="special">;</span>
  354. <span class="keyword">using</span> <span class="identifier">position_cache</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">position_cache</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">iterator_type</span><span class="special">&gt;&gt;;</span>
  355. <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span>
  356. <span class="identifier">parse</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">input</span><span class="special">,</span> <span class="identifier">position_cache</span><span class="special">&amp;</span> <span class="identifier">positions</span><span class="special">)</span>
  357. <span class="special">{</span>
  358. <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space</span><span class="special">;</span>
  359. <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="identifier">ast</span><span class="special">;</span>
  360. <span class="identifier">iterator_type</span> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">input</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span>
  361. <span class="identifier">iterator_type</span> <span class="keyword">const</span> <span class="identifier">end</span> <span class="special">=</span> <span class="identifier">input</span><span class="special">.</span><span class="identifier">end</span><span class="special">();</span>
  362. <span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">with</span><span class="special">;</span>
  363. <span class="comment">// Our parser</span>
  364. <span class="keyword">using</span> <span class="identifier">client</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">employees</span><span class="special">;</span>
  365. <span class="keyword">using</span> <span class="identifier">client</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">position_cache_tag</span><span class="special">;</span>
  366. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span>
  367. <span class="comment">// we pass our position_cache to the parser so we can access</span>
  368. <span class="comment">// it later in our on_sucess handlers</span>
  369. <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">position_cache_tag</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">positions</span><span class="special">))</span>
  370. <span class="special">[</span>
  371. <span class="identifier">employees</span>
  372. <span class="special">];</span>
  373. <span class="keyword">bool</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">phrase_parse</span><span class="special">(</span><span class="identifier">iter</span><span class="special">,</span> <span class="identifier">end</span><span class="special">,</span> <span class="identifier">parser</span><span class="special">,</span> <span class="identifier">space</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">);</span>
  374. <span class="comment">// ... Some error checking here</span>
  375. <span class="keyword">return</span> <span class="identifier">ast</span><span class="special">;</span>
  376. <span class="special">}</span>
  377. </pre>
  378. <p>
  379. Let's walk through the code.
  380. </p>
  381. <p>
  382. First, we have some typedefs for 1) The iterator type we are using for the
  383. parser, <code class="computeroutput"><span class="identifier">iterator_type</span></code> and
  384. 2) For the <code class="computeroutput"><span class="identifier">position_cache</span></code>
  385. type. The latter is a template that accepts the type of container it will
  386. hold. In this case, a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">iterator_type</span><span class="special">&gt;</span></code>.
  387. </p>
  388. <p>
  389. The main parse function accepts an input, a std::string and a reference to
  390. a position_cache, and retuns an AST: <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span></code>.
  391. </p>
  392. <p>
  393. Inside the parse function, we first create an AST where parsed data will
  394. be stored:
  395. </p>
  396. <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">employee</span><span class="special">&gt;</span> <span class="identifier">ast</span><span class="special">;</span>
  397. </pre>
  398. <p>
  399. Then finally, we create a parser, injecting a reference to the <code class="computeroutput"><span class="identifier">position_cache</span></code>, and call phrase_parse:
  400. </p>
  401. <pre class="programlisting"><span class="keyword">using</span> <span class="identifier">client</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">employees</span><span class="special">;</span>
  402. <span class="keyword">using</span> <span class="identifier">client</span><span class="special">::</span><span class="identifier">parser</span><span class="special">::</span><span class="identifier">position_cache_tag</span><span class="special">;</span>
  403. <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">parser</span> <span class="special">=</span>
  404. <span class="comment">// we pass our position_cache to the parser so we can access</span>
  405. <span class="comment">// it later in our on_sucess handlers</span>
  406. <span class="identifier">with</span><span class="special">&lt;</span><span class="identifier">position_cache_tag</span><span class="special">&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">positions</span><span class="special">))</span>
  407. <span class="special">[</span>
  408. <span class="identifier">employees</span>
  409. <span class="special">];</span>
  410. <span class="keyword">bool</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">phrase_parse</span><span class="special">(</span><span class="identifier">iter</span><span class="special">,</span> <span class="identifier">end</span><span class="special">,</span> <span class="identifier">parser</span><span class="special">,</span> <span class="identifier">space</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">);</span>
  411. </pre>
  412. <p>
  413. On successful parse, the AST, <code class="computeroutput"><span class="identifier">ast</span></code>,
  414. will contain the actual parsed data.
  415. </p>
  416. <h5>
  417. <a name="spirit_x3.tutorials.annotation.h9"></a>
  418. <span class="phrase"><a name="spirit_x3.tutorials.annotation.getting_the_source_positions"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.getting_the_source_positions">Getting
  419. The Source Positions</a>
  420. </h5>
  421. <p>
  422. Now that we have our main parse function, let's have an example sourcefile
  423. to parse and show how we can obtain the position of an AST element, returned
  424. after a successful parse.
  425. </p>
  426. <p>
  427. Given this input:
  428. </p>
  429. <pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">input</span> <span class="special">=</span> <span class="identifier">R</span><span class="string">"(
  430. {
  431. 23,
  432. "</span><span class="identifier">Amanda</span><span class="string">",
  433. "</span><span class="identifier">Stefanski</span><span class="string">",
  434. 1000.99
  435. },
  436. {
  437. 35,
  438. "</span><span class="identifier">Angie</span><span class="string">",
  439. "</span><span class="identifier">Chilcote</span><span class="string">",
  440. 2000.99
  441. },
  442. {
  443. 43,
  444. "</span><span class="identifier">Dannie</span><span class="string">",
  445. "</span><span class="identifier">Dillinger</span><span class="string">",
  446. 3000.99
  447. },
  448. {
  449. 22,
  450. "</span><span class="identifier">Dorene</span><span class="string">",
  451. "</span><span class="identifier">Dole</span><span class="string">",
  452. 2500.99
  453. },
  454. {
  455. 38,
  456. "</span><span class="identifier">Rossana</span><span class="string">",
  457. "</span><span class="identifier">Rafferty</span><span class="string">",
  458. 5000.99
  459. }
  460. )"</span><span class="special">;</span>
  461. </pre>
  462. <p>
  463. We call our parse function after instantiating a <code class="computeroutput"><span class="identifier">position_cache</span></code>
  464. object that will hold the source stream positions:
  465. </p>
  466. <pre class="programlisting"><span class="identifier">position_cache</span> <span class="identifier">positions</span><span class="special">{</span><span class="identifier">input</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">input</span><span class="special">.</span><span class="identifier">end</span><span class="special">()};</span>
  467. <span class="keyword">auto</span> <span class="identifier">ast</span> <span class="special">=</span> <span class="identifier">parse</span><span class="special">(</span><span class="identifier">input</span><span class="special">,</span> <span class="identifier">positions</span><span class="special">);</span>
  468. </pre>
  469. <p>
  470. We now have an AST, <code class="computeroutput"><span class="identifier">ast</span></code>,
  471. that contains the parsed results. Let us get the source positions of the
  472. 2nd employee:
  473. </p>
  474. <pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">positions</span><span class="special">.</span><span class="identifier">position_of</span><span class="special">(</span><span class="identifier">ast</span><span class="special">[</span><span class="number">1</span><span class="special">]);</span> <span class="comment">// zero based of course!</span>
  475. </pre>
  476. <p>
  477. <code class="computeroutput"><span class="identifier">pos</span></code> is an iterator range
  478. that contians iterators to the start and end of <code class="computeroutput"><span class="identifier">ast</span><span class="special">[</span><span class="number">1</span><span class="special">]</span></code>
  479. in the input stream.
  480. </p>
  481. <h5>
  482. <a name="spirit_x3.tutorials.annotation.h10"></a>
  483. <span class="phrase"><a name="spirit_x3.tutorials.annotation.config"></a></span><a class="link" href="annotation.html#spirit_x3.tutorials.annotation.config">Config</a>
  484. </h5>
  485. <p>
  486. If you read the previous <a class="link" href="minimal.html" title="X3 Program Structure">Program
  487. Structure</a> tutorial where we separated various logical modules of the
  488. parser into separate cpp and header files, and you are wondering how to provide
  489. the context configuration information (see <a class="link" href="minimal.html#tutorial_configuration">Config
  490. Section</a>), we need to supplement the context like this:
  491. </p>
  492. <pre class="programlisting"><span class="keyword">using</span> <span class="identifier">phrase_context_type</span> <span class="special">=</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">phrase_parse_context</span><span class="special">&lt;</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">ascii</span><span class="special">::</span><span class="identifier">space_type</span><span class="special">&gt;::</span><span class="identifier">type</span><span class="special">;</span>
  493. <span class="keyword">typedef</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">context</span><span class="special">&lt;</span>
  494. <span class="identifier">error_handler_tag</span>
  495. <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">reference_wrapper</span><span class="special">&lt;</span><span class="identifier">position_cache</span><span class="special">&gt;</span>
  496. <span class="special">,</span> <span class="identifier">phrase_context_type</span><span class="special">&gt;</span>
  497. <span class="identifier">context_type</span><span class="special">;</span>
  498. </pre>
  499. </div>
  500. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  501. <td align="left"></td>
  502. <td align="right"><div class="copyright-footer">Copyright &#169; 2001-2018 Joel de Guzman,
  503. Hartmut Kaiser<p>
  504. Distributed under the Boost Software License, Version 1.0. (See accompanying
  505. file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
  506. </p>
  507. </div></td>
  508. </tr></table>
  509. <hr>
  510. <div class="spirit-nav">
  511. <a accesskey="p" href="minimal.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorials.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rexpr.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
  512. </div>
  513. </body>
  514. </html>