the_lazy_parser.html 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <html>
  2. <head>
  3. <title>The Lazy Parsers</title>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. <link rel="stylesheet" href="theme/style.css" type="text/css">
  6. </head>
  7. <body>
  8. <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
  9. <tr>
  10. <td width="10">
  11. </td>
  12. <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>The
  13. Lazy Parser</b></font></td>
  14. <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
  15. </tr>
  16. </table>
  17. <br>
  18. <table border="0">
  19. <tr>
  20. <td width="10"></td>
  21. <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
  22. <td width="30"><a href="dynamic_parsers.html"><img src="theme/l_arr.gif" border="0"></a></td>
  23. <td width="30"><a href="select_parser.html"><img src="theme/r_arr.gif" border="0"></a></td>
  24. </tr>
  25. </table>
  26. <p>Closures are cool. It allows us to inject stack based local variables anywhere
  27. in our parse descent hierarchy. Typically, we store temporary variables, generated
  28. by our semantic actions, in our closure variables, as a means to pass information
  29. up and down the recursive descent.</p>
  30. <p>Now imagine this... Having in mind that closure variables can be just about
  31. any type, we can store a parser, a rule, or a pointer to a parser or rule, in
  32. a closure variable. <em>Yeah, right, so what?...</em> Ok, hold on... What if
  33. we can use this closure variable to initiate a parse? Think about it for a second.
  34. Suddenly we'll have some powerful dynamic parsers! Suddenly we'll have a full
  35. round trip from to <a href="../phoenix/index.html">Phoenix</a> and Spirit and
  36. back! <a href="../phoenix/index.html">Phoenix</a> semantic actions choose the
  37. right Spirit parser and Spirit parsers choose the right <a href="../phoenix/index.html">Phoenix</a>
  38. semantic action. Oh MAN, what a honky cool idea, I might say!!</p>
  39. <h2>lazy_p</h2>
  40. <p>This is the idea behind the <tt>lazy_p</tt> parser. The <tt>lazy_p</tt> syntax
  41. is:</p>
  42. <pre> lazy_p<span class="special">(</span>actor<span class="special">)</span></pre>
  43. <p>where actor is a <a href="../phoenix/index.html">Phoenix</a> expression that
  44. returns a Spirit parser. This returned parser is used in the parsing process.
  45. </p>
  46. <p>Example: </p>
  47. <pre> lazy_p<span class="special">(</span>phoenix<span class="special">::</span>val<span class="special">(</span>int_p<span class="special">))[</span>assign_a<span class="special">(</span>result<span class="special">)]</span>
  48. </pre>
  49. <p>Semantic actions attached to the <tt>lazy_p</tt> parser expects the same signature
  50. as that of the returned parser (<tt>int_p</tt>, in our example above).</p>
  51. <h2>lazy_p example</h2>
  52. <p>To give you a better glimpse (see the <tt><a href="../example/intermediate/lazy_parser.cpp">lazy_parser.cpp</a></tt>),
  53. say you want to parse inputs such as:</p>
  54. <pre> <span class=identifier>dec
  55. </span><span class="special">{</span><span class=identifier><br> 1 2 3<br> bin
  56. </span><span class="special">{</span><span class=identifier><br> 1 10 11<br> </span><span class="special">}</span><span class=identifier><br> 4 5 6<br> </span><span class="special">}</span></pre>
  57. <p>where <tt>bin {...}</tt> and <tt>dec {...}</tt> specifies the numeric format
  58. (binary or decimal) that we are expecting to read. If we analyze the input,
  59. we want a grammar like:</p>
  60. <pre><code><font color="#000000"><span class=special> </span><span class=identifier>base </span><span class="special">=</span><span class=identifier> </span><span class="string">&quot;bin&quot;</span><span class=identifier> </span><span class="special">|</span><span class=identifier> </span><span class="string">&quot;dec&quot;</span><span class="special">;</span><span class=identifier>
  61. block </span><span class=special>= </span><span class="identifier">base</span><span class=special> &gt;&gt; </span><span class="literal">'{'</span><span class=special> &gt;&gt; *</span><span class="identifier">block_line</span><span class=special> &gt;&gt; </span><span class="literal">'}'</span><span class=special>;
  62. </span>block_line <span class=special>= </span><span class="identifier">number</span><span class=special> | </span><span class=identifier>block</span><span class=special>;</span></font></code></pre>
  63. <p>We intentionally left out the <code><font color="#000000"><span class="identifier"><tt>number</tt></span></font></code>
  64. rule. The tricky part is that the way <tt>number</tt> rule behaves depends on
  65. the result of the <tt>base</tt> rule. If <tt>base</tt> got a <em>&quot;bin&quot;</em>,
  66. then number should parse binary numbers. If <tt>base</tt> got a <em>&quot;dec&quot;</em>,
  67. then number should parse decimal numbers. Typically we'll have to rewrite our
  68. grammar to accomodate the different parsing behavior:</p>
  69. <pre><code><font color="#000000"><span class=identifier> block </span><span class=special>=
  70. </span><span class=identifier>&quot;bin&quot;</span> <span class=special>&gt;&gt; </span><span class="literal">'{'</span><span class=special> &gt;&gt; *</span>bin_line<span class=special> &gt;&gt; </span><span class="literal">'}'</span><span class=special>
  71. | </span><span class=identifier>&quot;dec&quot;</span> <span class=special>&gt;&gt; </span><span class="literal">'{'</span><span class=special> &gt;&gt; *</span>dec_line<span class=special> &gt;&gt; </span><span class="literal">'}'</span><span class=special>
  72. ;
  73. </span>bin_line <span class=special>= </span><span class="identifier">bin_p</span><span class=special> | </span><span class=identifier>block</span><span class=special>;
  74. </span>dec_line <span class=special>= </span><span class="identifier">int_p</span><span class=special> | </span><span class=identifier>block</span><span class=special>;</span></font></code></pre>
  75. <p>while this is fine, the redundancy makes us want to find a better solution;
  76. after all, we'd want to make full use of Spirit's dynamic parsing capabilities.
  77. Apart from that, there will be cases where the set of parsing behaviors for
  78. our <tt>number</tt> rule is not known when the grammar is written. We'll only
  79. be given a map of string descriptors and corresponding rules [e.g. ((&quot;dec&quot;,
  80. int_p), (&quot;bin&quot;, bin_p) ... etc...)].</p>
  81. <p>The basic idea is to have a rule for binary and decimal numbers. That's easy
  82. enough to do (see <a href="numerics.html">numerics</a>). When <tt>base</tt>
  83. is being parsed, in your semantic action, store a pointer to the selected base
  84. in a closure variable (e.g. <tt>block.int_rule</tt>). Here's an example:</p>
  85. <pre><code><font color="#000000"><span class=special> </span><span class=identifier>base
  86. </span><span class="special">=</span><span class=identifier> str_p</span><span class="special">(</span><span class="string">&quot;bin&quot;</span><span class="special">)[</span><span class=identifier>block.int_rule</span> = <span class="special">&amp;</span>var<span class="special">(</span><span class="identifier">bin_rule</span><span class="special">)]
  87. | </span><span class=identifier>str_p</span><span class="special">(</span><span class="string">&quot;dec&quot;</span><span class="special">)[</span><span class=identifier>block.int_rule</span> = <span class="special">&amp;</span>var<span class="special">(</span><span class="identifier">dec_rule</span><span class="special">)]
  88. ;</span></font></code></pre>
  89. <p>With this setup, your number rule will now look something like:</p>
  90. <pre><code><font color="#000000"><span class=special> </span><span class=identifier>number </span><span class="special">=</span><span class=identifier> lazy_p</span><span class="special">(*</span><span class=identifier>block.int_rule</span><span class="special">);</span></font></code></pre>
  91. <p>The <tt><a href="../example/intermediate/lazy_parser.cpp">lazy_parser.cpp</a></tt>
  92. does it a bit differently, ingeniously using the <a href="symbols.html">symbol
  93. table</a> to dispatch the correct rule, but in essence, both strategies are
  94. similar. This technique, using the symbol table, is detailed in the Techiques section: <a href="techniques.html#nabialek_trick">nabialek_trick</a>. Admitedly, when you add up all the rules, the resulting grammar is
  95. more complex than the hard-coded grammar above. Yet, for more complex grammar
  96. patterns with a lot more rules to choose from, the additional setup is well
  97. worth it.</p>
  98. <table border="0">
  99. <tr>
  100. <td width="10"></td>
  101. <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
  102. <td width="30"><a href="dynamic_parsers.html"><img src="theme/l_arr.gif" border="0"></a></td>
  103. <td width="30"><a href="select_parser.html"><img src="theme/r_arr.gif" border="0"></a></td>
  104. </tr>
  105. </table>
  106. <br>
  107. <hr size="1">
  108. <p class="copyright">Copyright &copy; 2003 Joel de Guzman<br>
  109. Copyright &copy; 2003 Vaclav Vesely<br>
  110. <br>
  111. <font size="2">Use, modification and distribution is subject to the Boost Software
  112. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  113. http://www.boost.org/LICENSE_1_0.txt)</font></p>
  114. <p class="copyright">&nbsp;</p>
  115. </body>
  116. </html>