switch_parser.html 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <html>
  2. <head>
  3. <title>The Switch Parser</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. <style type="text/css">
  7. <!--
  8. .style1 {font-family: "Courier New", Courier, mono}
  9. .style3 {font-family: "Courier New", Courier, mono; color: #FF0000; }
  10. -->
  11. </style>
  12. </head>
  13. <body>
  14. <table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
  15. <tr>
  16. <td width="10"> </td>
  17. <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>The Switch Parser </b></font></td>
  18. <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
  19. </tr>
  20. </table>
  21. <br>
  22. <table border="0">
  23. <tr>
  24. <td width="10"></td>
  25. <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
  26. <td width="30"><a href="select_parser.html"><img src="theme/l_arr.gif" border="0"></a></td>
  27. <td width="30"><a href="escape_char_parser.html"><img src="theme/r_arr.gif" border="0"></a></td>
  28. </tr>
  29. </table>
  30. <p>Switch parsers may be used to simplify certain alternation constructs. Consider the following code:</p>
  31. <pre> rule<span class="special">&lt;&gt;</span> rule_overall <span class="special">=</span>
  32. ch_p<span class="special">(</span><span class="literal">'a'</span><span class="special">)</span> <span class="special">&gt;&gt;</span> parser_a
  33. <span class="special">|</span> ch_p<span class="special">(</span><span class="literal">'b'</span><span class="special">)</span> <span class="special">&gt;&gt;</span> parser_b
  34. <span class="comment">// ...</span>
  35. <span class="special">|</span> ch_p<span class="special">(</span><span class="literal">'n'</span><span class="special">)</span> <span class="special">&gt;&gt;</span> parser_n
  36. <span class="special">;</span></pre>
  37. <p>Each of the alternatives are evaluated normally in a sequential manner. This tend to be inefficient, especially for a large number of alternatives. To avoid this inefficiency and to make it possible to write such constructs in a more readable form, Spirit contains the <tt>switch_p</tt> family of parsers. The switch_p parser allows us to rewrite the previous construct as:</p>
  38. <pre> rule<span class="special">&lt;&gt;</span> rule_overall <span class="special">=</span>
  39. switch_p
  40. <span class="special">[</span>
  41. case_p<span class="special">&lt;</span><span class="literal">'a'</span><span class="special">&gt;(</span>parser_a<span class="special">),</span>
  42. case_p<span class="special">&lt;</span><span class="literal">'b'</span><span class="special">&gt;(</span>parser_b<span class="special">),</span>
  43. <span class="comment"> // ...</span>
  44. case_p<span class="special">&lt;</span><span class="literal">'n'</span><span class="special">&gt;(</span>parser_n<span class="special">)</span>
  45. ]
  46. ;</pre>
  47. <p>This <tt>switch_p</tt> parser takes the next character (or token) from the input stream and tries to match it against the given integral compile time constants supplied as the template parameters to the <tt>case_p</tt> parsers. If this character matches one of the <tt>case_p</tt> branches, the associated parser is executed (i.e. if 'a' is matched, <tt>parser_a</tt> is executed, if 'b' is matched, <tt>parser_b</tt> is executed and so on) . If no <tt>case_p</tt> branch matches the next input character, the overall construct does not match at all. </p>
  48. <table width="80%" border="0" align="center">
  49. <tr>
  50. <td class="note_box"><div align="justify"><img src="theme/bulb.gif" width="13" height="18"><strong> Nabialek trick </strong><br>
  51. <br>
  52. The <strong><em><a href="techniques.html#nabialek_trick">&quot;Nabialek trick&quot; </a></em></strong>(from the name of its inventor, Sam Nabialek), can also improve the rule dispatch from linear non-deterministic to deterministic. This is similar to the <tt>switch_p</tt> parser, yet, can handle grammars where a keyword (operator, etc), instead of a single character or token, precedes a production.</div></td>
  53. </tr>
  54. </table>
  55. <p>Sometimes it is desireable to add handling of the default case (none of the <tt>case_p</tt> branches matched). This may be achieved with the help of a <tt>default_p</tt> branch:</p>
  56. <pre> rule<span class="special">&lt;&gt;</span> rule_overall <span class="special">=</span>
  57. switch_p
  58. <span class="special">[</span>
  59. case_p<span class="special">&lt;</span><span class="literal">'a'</span><span class="special">&gt;(</span>parser_a<span class="special">),</span>
  60. case_p<span class="special">&lt;</span><span class="literal">'b'</span><span class="special">&gt;(</span>parser_b<span class="special">),</span>
  61. <span class="comment"> // ...</span>
  62. case_p<span class="special">&lt;</span><span class="literal">'n'</span><span class="special">&gt;(</span>parser_n<span class="special">),</span>
  63. default_p<span class="special">(</span>parser_default<span class="special">)</span>
  64. <span class="special">]
  65. ;</span></pre>
  66. <p>This form chooses the <tt>parser_default</tt> parser if none of the cases matches the next character from the input stream. Please note that, obviously, only one <tt>default_p</tt> branch may be added to the <tt>switch_p</tt> parser construct. </p>
  67. <p>Moreover, it is possible to omit the parentheses and body from the <tt>default_p</tt> construct, in which case, no additional parser is executed and the overall <tt>switch_p</tt> construct simply returns a match on any character of the input stream, which does not match any of the <tt>case_p</tt> branches:</p>
  68. <pre> rule<span class="special">&lt;&gt;</span> rule_overall <span class="special">=</span>
  69. switch_p
  70. <span class="special">[</span>
  71. case_p<span class="special">&lt;</span><span class="literal">'a'</span><span class="special">&gt;(</span>parser_a<span class="special">),</span>
  72. case_p<span class="special">&lt;</span><span class="literal">'b'</span><span class="special">&gt;(</span>parser_b<span class="special">),</span>
  73. <span class="comment">// ...</span>
  74. case_p<span class="special">&lt;</span><span class="literal">'n'</span><span class="special">&gt;(</span>parser_n<span class="special">),</span>
  75. default_p
  76. <span class="special">]</span>
  77. ;</pre>
  78. <p>There is another form of the switch_p construct. This form allows us to explicitly specify the value to be used for matching against the <tt>case_p</tt> branches: </p>
  79. <pre> rule<span class="special">&lt;&gt;</span> rule_overall <span class="special">=</span>
  80. switch_p<span class="special">(</span>cond<span class="special">)</span>
  81. <span class="special">[</span>
  82. case_p<span class="special">&lt;</span><span class="literal">'a'</span><span class="special">&gt;(</span>parser_a<span class="special">),</span>
  83. case_p<span class="special">&lt;</span><span class="literal">'b'</span><span class="special">&gt;(</span>parser_b<span class="special">),</span>
  84. <span class="comment"> // ...</span>
  85. case_p<span class="special">&lt;</span><span class="literal">'n'</span><span class="special">&gt;(</span>parser_n<span class="special">)</span>
  86. <span class="special">]</span>
  87. ;</pre>
  88. <p>where <tt>cond</tt> is a parser or a nullary function or function object (functor). If it is a parser, then it is tried and its return value is used to match against the <tt>case_p</tt> branches. If it is a nullary function or functor, then its return value will be used. </p>
  89. <p>Please note that during its compilation, the <tt>switch_p</tt> construct is transformed into a real C++ <tt>switch</tt> statement. This makes the runtime execution very efficient. </p>
  90. <table width="80%" border="0" align="center">
  91. <tr>
  92. <td class="note_box"><p><img src="theme/alert.gif" width="16" height="16"> <tt>BOOST_SPIRIT_SWITCH_CASE_LIMIT</tt><br>
  93. <br>
  94. The number of possible <tt>case_p</tt>/<tt>default_p</tt> branches is limited by the Spirit compile time constant <tt>BOOST_SPIRIT_SWITCH_CASE_LIMIT</tt>, which defaults to 3. There is no theoretical upper limit for this constant, but most compilers won't allow you to specify a very large number.</p>
  95. <p>Example:</p>
  96. <p class="style1"><span class="comment">// Define these before including switch.hpp <br>
  97. </span><span class="preprocessor">#define</span> BOOST_SPIRIT_SWITCH_CASE_LIMIT 10 </p></td>
  98. </tr>
  99. </table><br>
  100. <table border="0">
  101. <tr>
  102. <td width="10"></td>
  103. <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
  104. <td width="30"><a href="select_parser.html"><img src="theme/l_arr.gif" border="0"></a></td>
  105. <td width="30"><a href="escape_char_parser.html"><img src="theme/r_arr.gif" border="0"></a></td>
  106. </tr>
  107. </table>
  108. <br>
  109. <hr size="1">
  110. <p class="copyright">Copyright &copy; 2003-2004 Hartmut Kaiser <br>
  111. <br>
  112. <font size="2">Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) </font> </p>
  113. </body>
  114. </html>