• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>RExpressions - Recursive 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="annotation.html" title="Annotations - Decorating the ASTs">
10<link rel="next" href="error_handling.html" title="Error Handling">
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="annotation.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="error_handling.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.rexpr"></a><a class="link" href="rexpr.html" title="RExpressions - Recursive ASTs!">RExpressions - Recursive ASTs!</a>
28</h3></div></div></div>
29<p>
30        In this example, we'll explore more on how to create heierarchical ASTs.
31        We will parse a minimalistic JSON-like language and compile the results into
32        our data structures in the form of a tree.
33      </p>
34<p>
35        <span class="emphasis"><em>rexpr</em></span> is a parser for RExpressions, a language resembling
36        a minimal subset of json, limited to a dictionary (composed of key=value
37        pairs) where the value can itself be a string or a recursive dictionary.
38      </p>
39<p>
40        Here's an Example:
41      </p>
42<pre class="programlisting"><span class="special">{</span>
43    <span class="string">"color"</span> <span class="special">=</span> <span class="string">"blue"</span>
44    <span class="string">"size"</span> <span class="special">=</span> <span class="string">"29 cm."</span>
45    <span class="string">"position"</span> <span class="special">=</span> <span class="special">{</span>
46        <span class="string">"x"</span> <span class="special">=</span> <span class="string">"123"</span>
47        <span class="string">"y"</span> <span class="special">=</span> <span class="string">"456"</span>
48    <span class="special">}</span>
49<span class="special">}</span>
50</pre>
51<p>
52        This simple parser for X3 is intended as a minimal starting point. It is
53        minimal, yet complete with all things necessary parts that make up rules
54        (and grammars), except error handling and reporting.
55      </p>
56<p>
57        The example can be found here: <a href="../../../../../example/x3/rexpr/rexpr_min/rexpr.cpp" target="_top">rexpr.cpp</a>
58      </p>
59<p>
60        The same parser, but complete with error handling and reporting, better file
61        organization, separate compilation of grammars, and a full test harness,
62        can be found in this directory:
63      </p>
64<p>
65        <a href="../../../../../example/x3/rexpr/rexpr_full/" target="_top">rexpr/rexpr_full/</a>
66      </p>
67<div class="note"><table border="0" summary="Note">
68<tr>
69<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
70<th align="left">Note</th>
71</tr>
72<tr><td align="left" valign="top"><p>
73          rexpr_full is the canonical structure proposed as best practice on how
74          parsers are written using Spirit X3.
75        </p></td></tr>
76</table></div>
77<h5>
78<a name="spirit_x3.tutorials.rexpr.h0"></a>
79        <span class="phrase"><a name="spirit_x3.tutorials.rexpr.the_ast"></a></span><a class="link" href="rexpr.html#spirit_x3.tutorials.rexpr.the_ast">The
80        AST</a>
81      </h5>
82<p>
83        Here's the AST:
84      </p>
85<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>
86<span class="special">{</span>
87    <span class="keyword">namespace</span> <span class="identifier">x3</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>
88
89    <span class="keyword">struct</span> <span class="identifier">rexpr</span><span class="special">;</span>
90
91    <span class="keyword">struct</span> <span class="identifier">rexpr_value</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span>
92            <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span>
93          <span class="special">,</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">forward_ast</span><span class="special">&lt;</span><span class="identifier">rexpr</span><span class="special">&gt;</span>
94        <span class="special">&gt;</span>
95    <span class="special">{</span>
96        <span class="keyword">using</span> <span class="identifier">base_type</span><span class="special">::</span><span class="identifier">base_type</span><span class="special">;</span>
97        <span class="keyword">using</span> <span class="identifier">base_type</span><span class="special">::</span><span class="keyword">operator</span><span class="special">=;</span>
98    <span class="special">};</span>
99
100    <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">rexpr_value</span><span class="special">&gt;</span> <span class="identifier">rexpr_map</span><span class="special">;</span>
101    <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">rexpr_value</span><span class="special">&gt;</span> <span class="identifier">rexpr_key_value</span><span class="special">;</span>
102
103    <span class="keyword">struct</span> <span class="identifier">rexpr</span>
104    <span class="special">{</span>
105        <span class="identifier">rexpr_map</span> <span class="identifier">entries</span><span class="special">;</span>
106    <span class="special">};</span>
107<span class="special">}}</span>
108</pre>
109<p>
110        <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">variant</span></code> is a support utility in Spirit
111        X3 that extends <a href="http://www.boost.org/doc/html/variant.html" target="_top">Boost.Variant</a>.
112        Typically, you use <a href="http://www.boost.org/doc/html/variant.html" target="_top">Boost.Variant</a>
113        right out of the box and refer to a particular template instantiation using
114        a typedef. For example:
115      </p>
116<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">my_variant</span><span class="special">;</span>
117</pre>
118<p>
119        Instead of doing that, we create a <code class="computeroutput"><span class="keyword">class</span></code>
120        (or <code class="computeroutput"><span class="keyword">struct</span></code> in the case) that
121        subclasses from <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">variant</span></code>. By making the variant a subclass,
122        you have a distinct type in your namespace. You also have control of the
123        constructors and assignment operators, as well as giving you the freedom
124        to add more functionality.
125      </p>
126<p>
127        <code class="computeroutput"><span class="identifier">rexpr_value</span></code> has two variant
128        elements. It can either be a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
129        or a <code class="computeroutput"><span class="identifier">rexpr</span></code>. Since <code class="computeroutput"><span class="identifier">rexpr</span></code> recursively contains a <code class="computeroutput"><span class="identifier">rexpr_value</span></code>, it has to be forward declared.
130        This recursive data structure requires <code class="computeroutput"><span class="identifier">rexpr</span></code>
131        to be wrapped in a <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">forward_ast</span></code> as shown in the declaration.
132      </p>
133<p>
134        We need to tell fusion about our <code class="computeroutput"><span class="identifier">rexpr</span></code>
135        struct to make it a first-class fusion citizen:
136      </p>
137<pre class="programlisting"><span class="identifier">BOOST_FUSION_ADAPT_STRUCT</span><span class="special">(</span>
138    <span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr</span><span class="special">,</span>
139    <span class="identifier">entries</span>
140<span class="special">)</span>
141</pre>
142<p>
143        So essentially, a <code class="computeroutput"><span class="identifier">rexpr_value</span></code>
144        value is either a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> or a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">rexpr_value</span><span class="special">&gt;</span></code>.
145      </p>
146<h5>
147<a name="spirit_x3.tutorials.rexpr.h1"></a>
148        <span class="phrase"><a name="spirit_x3.tutorials.rexpr.walking_the_ast"></a></span><a class="link" href="rexpr.html#spirit_x3.tutorials.rexpr.walking_the_ast">Walking
149        the AST</a>
150      </h5>
151<p>
152        We add a utility to print out the AST:
153      </p>
154<pre class="programlisting"><span class="keyword">int</span> <span class="keyword">const</span> <span class="identifier">tabsize</span> <span class="special">=</span> <span class="number">4</span><span class="special">;</span>
155
156<span class="keyword">struct</span> <span class="identifier">rexpr_printer</span>
157<span class="special">{</span>
158    <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">result_type</span><span class="special">;</span>
159
160    <span class="identifier">rexpr_printer</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">indent</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span>
161      <span class="special">:</span> <span class="identifier">indent</span><span class="special">(</span><span class="identifier">indent</span><span class="special">)</span> <span class="special">{}</span>
162
163    <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">rexpr</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">ast</span><span class="special">)</span> <span class="keyword">const</span>
164    <span class="special">{</span>
165        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'{'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
166        <span class="keyword">for</span> <span class="special">(</span><span class="keyword">auto</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">entry</span> <span class="special">:</span> <span class="identifier">ast</span><span class="special">.</span><span class="identifier">entries</span><span class="special">)</span>
167        <span class="special">{</span>
168            <span class="identifier">tab</span><span class="special">(</span><span class="identifier">indent</span><span class="special">+</span><span class="identifier">tabsize</span><span class="special">);</span>
169            <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'"'</span> <span class="special">&lt;&lt;</span> <span class="identifier">entry</span><span class="special">.</span><span class="identifier">first</span> <span class="special">&lt;&lt;</span> <span class="string">"\" = "</span><span class="special">;</span>
170            <span class="identifier">boost</span><span class="special">::</span><span class="identifier">apply_visitor</span><span class="special">(</span><span class="identifier">rexpr_printer</span><span class="special">(</span><span class="identifier">indent</span><span class="special">+</span><span class="identifier">tabsize</span><span class="special">),</span> <span class="identifier">entry</span><span class="special">.</span><span class="identifier">second</span><span class="special">);</span>
171        <span class="special">}</span>
172        <span class="identifier">tab</span><span class="special">(</span><span class="identifier">indent</span><span class="special">);</span>
173        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'}'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
174    <span class="special">}</span>
175
176    <span class="keyword">void</span> <span class="keyword">operator</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">text</span><span class="special">)</span> <span class="keyword">const</span>
177    <span class="special">{</span>
178        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'"'</span> <span class="special">&lt;&lt;</span> <span class="identifier">text</span> <span class="special">&lt;&lt;</span> <span class="char">'"'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
179    <span class="special">}</span>
180
181    <span class="keyword">void</span> <span class="identifier">tab</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">spaces</span><span class="special">)</span> <span class="keyword">const</span>
182    <span class="special">{</span>
183        <span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">spaces</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
184            <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span><span class="special">;</span>
185    <span class="special">}</span>
186
187    <span class="keyword">int</span> <span class="identifier">indent</span><span class="special">;</span>
188<span class="special">};</span>
189</pre>
190<p>
191        Traversing the AST is a recursive exercise. <code class="computeroutput"><span class="identifier">rexpr_printer</span></code>
192        is a function object and the main entry point is <code class="computeroutput"><span class="keyword">void</span>
193        <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">rexpr</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">ast</span><span class="special">)</span></code>. Notice how it recursively calls an instance
194        of itself for each of the key value pairs, using <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">apply_visitor</span></code>.
195        Before and after iterating through all the elements in the map, the braces
196        are printed to surround the entire body, taking care of correct indentation
197        at each point in the recursive traversal.
198      </p>
199<p>
200        The <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code>
201        for <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> should be self explanatory. It simply
202        prints the text inside double quotes.
203      </p>
204<h5>
205<a name="spirit_x3.tutorials.rexpr.h2"></a>
206        <span class="phrase"><a name="spirit_x3.tutorials.rexpr.the_grammar"></a></span><a class="link" href="rexpr.html#spirit_x3.tutorials.rexpr.the_grammar">The
207        Grammar</a>
208      </h5>
209<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">parser</span>
210<span class="special">{</span>
211    <span class="keyword">namespace</span> <span class="identifier">x3</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>
212    <span class="keyword">namespace</span> <span class="identifier">ascii</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">ascii</span><span class="special">;</span>
213
214    <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">lit</span><span class="special">;</span>
215    <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">;</span>
216
217    <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span>
218    <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">string</span><span class="special">;</span>
219
220    <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">rexpr_value</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr_value</span><span class="special">&gt;</span>
221        <span class="identifier">rexpr_value</span> <span class="special">=</span> <span class="string">"rexpr_value"</span><span class="special">;</span>
222
223    <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">rexpr</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr</span><span class="special">&gt;</span>
224        <span class="identifier">rexpr</span> <span class="special">=</span> <span class="string">"rexpr"</span><span class="special">;</span>
225
226    <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">rexpr_key_value</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr_key_value</span><span class="special">&gt;</span>
227        <span class="identifier">rexpr_key_value</span> <span class="special">=</span> <span class="string">"rexpr_key_value"</span><span class="special">;</span>
228
229    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">quoted_string</span> <span class="special">=</span>
230        <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>
231
232    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">rexpr_value_def</span> <span class="special">=</span>
233        <span class="identifier">quoted_string</span> <span class="special">|</span> <span class="identifier">rexpr</span><span class="special">;</span>
234
235    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">rexpr_key_value_def</span> <span class="special">=</span>
236        <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">rexpr_value</span><span class="special">;</span>
237
238    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">rexpr_def</span> <span class="special">=</span>
239        <span class="char">'{'</span> <span class="special">&gt;&gt;</span> <span class="special">*</span><span class="identifier">rexpr_key_value</span> <span class="special">&gt;&gt;</span> <span class="char">'}'</span><span class="special">;</span>
240
241    <span class="identifier">BOOST_SPIRIT_DEFINE</span><span class="special">(</span><span class="identifier">rexpr_value</span><span class="special">,</span> <span class="identifier">rexpr</span><span class="special">,</span> <span class="identifier">rexpr_key_value</span><span class="special">);</span>
242<span class="special">}}</span>
243</pre>
244<p>
245        We declare three rules <code class="computeroutput"><span class="identifier">rexpr_value</span></code>,
246        <code class="computeroutput"><span class="identifier">rexpr</span></code> and <code class="computeroutput"><span class="identifier">rexpr_key_value</span></code>.
247        Same deal as before. The attributes declared for each rule are the same structures
248        we declared in our AST above. These are the structures our rules will produce.
249      </p>
250<p>
251        So, going top-down (from the start rule), <code class="computeroutput"><span class="identifier">rexpr</span></code>
252        is defined as zero or more <code class="computeroutput"><span class="identifier">rexpr_key_value</span></code>s
253        enclosed inside the curly braces. That's the kleene star in action there:
254        <code class="computeroutput"><span class="special">*</span><span class="identifier">rexpr_key_value</span></code>.
255      </p>
256<div class="note"><table border="0" summary="Note">
257<tr>
258<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
259<th align="left">Note</th>
260</tr>
261<tr><td align="left" valign="top"><p>
262          Take note of the convention: we use <code class="computeroutput"><span class="identifier">rexpr</span></code>
263          name as the rule name and <code class="computeroutput"><span class="identifier">rexpr_def</span></code>
264          as the rule definition name.
265        </p></td></tr>
266</table></div>
267<p>
268        To make the grammar clean, we capture the <code class="computeroutput"><span class="identifier">quoted_string</span></code>
269        production using C++ <code class="computeroutput"><span class="keyword">auto</span></code>.
270      </p>
271<p>
272        <code class="computeroutput"><span class="identifier">rexpr_value</span></code> is a <code class="computeroutput"><span class="identifier">quoted_string</span></code> followed by the assignment
273        operator <code class="computeroutput"><span class="char">'='</span></code>, followed by a <code class="computeroutput"><span class="identifier">rexpr_value</span></code>. <code class="computeroutput"><span class="identifier">rexpr_value</span></code>
274        is a <code class="computeroutput"><span class="identifier">quoted_string</span></code> <span class="emphasis"><em>OR</em></span>
275        a <code class="computeroutput"><span class="identifier">rexpr</span></code>. This uses the alternative
276        operator <code class="computeroutput"><span class="special">|</span></code>, and maps nicely
277        to the variant AST the rule is associated with.
278      </p>
279<p>
280        Finally, we associate the rules and their definitions:
281      </p>
282<pre class="programlisting"><span class="identifier">BOOST_SPIRIT_DEFINE</span><span class="special">(</span><span class="identifier">rexpr_value</span><span class="special">,</span> <span class="identifier">rexpr</span><span class="special">,</span> <span class="identifier">rexpr_key_value</span><span class="special">);</span>
283</pre>
284</div>
285<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
286<td align="left"></td>
287<td align="right"><div class="copyright-footer">Copyright © 2001-2018 Joel de Guzman,
288      Hartmut Kaiser<p>
289        Distributed under the Boost Software License, Version 1.0. (See accompanying
290        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>)
291      </p>
292</div></td>
293</tr></table>
294<hr>
295<div class="spirit-nav">
296<a accesskey="p" href="annotation.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="error_handling.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
297</div>
298</body>
299</html>
300