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"><</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"><</span><span class="identifier">rexpr</span><span class="special">></span> 94 <span class="special">></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"><</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">></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"><</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">></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"><</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">></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"><</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">></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">&</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"><<</span> <span class="char">'{'</span> <span class="special"><<</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">&</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"><<</span> <span class="char">'"'</span> <span class="special"><<</span> <span class="identifier">entry</span><span class="special">.</span><span class="identifier">first</span> <span class="special"><<</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"><<</span> <span class="char">'}'</span> <span class="special"><<</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">&</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"><<</span> <span class="char">'"'</span> <span class="special"><<</span> <span class="identifier">text</span> <span class="special"><<</span> <span class="char">'"'</span> <span class="special"><<</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"><</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"><<</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">&</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"><</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">></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"><</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">></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"><</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">></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">>></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">>></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">>></span> <span class="char">'='</span> <span class="special">>></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">>></span> <span class="special">*</span><span class="identifier">rexpr_key_value</span> <span class="special">>></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