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">
8 .style1 {font-family: "Courier New", Courier, mono}
9 .style3 {font-family: "Courier New", Courier, mono; color: #FF0000; }
15 <table width=
"100%" border=
"0" background=
"theme/bkd2.gif" cellspacing=
"2">
18 <td width=
"85%"> <font size=
"6" face=
"Verdana, Arial, Helvetica, sans-serif"><b>The Switch Parser
</b></font></td>
19 <td width=
"112"><a href=
"http://spirit.sf.net"><img src=
"theme/spirit.gif" width=
"112" height=
"48" align=
"right" border=
"0"></a></td>
26 <td width=
"30"><a href=
"../index.html"><img src=
"theme/u_arr.gif" border=
"0"></a></td>
27 <td width=
"30"><a href=
"select_parser.html"><img src=
"theme/l_arr.gif" border=
"0"></a></td>
28 <td width=
"30"><a href=
"escape_char_parser.html"><img src=
"theme/r_arr.gif" border=
"0"></a></td>
31 <p>Switch parsers may be used to simplify certain alternation constructs. Consider the following code:
</p>
32 <pre> rule
<span class=
"special"><></span> rule_overall
<span class=
"special">=
</span>
33 ch_p
<span class=
"special">(
</span><span class=
"literal">'a'
</span><span class=
"special">)
</span> <span class=
"special">>></span> parser_a
34 <span class=
"special">|
</span> ch_p
<span class=
"special">(
</span><span class=
"literal">'b'
</span><span class=
"special">)
</span> <span class=
"special">>></span> parser_b
35 <span class=
"comment">// ...
</span>
36 <span class=
"special">|
</span> ch_p
<span class=
"special">(
</span><span class=
"literal">'n'
</span><span class=
"special">)
</span> <span class=
"special">>></span> parser_n
37 <span class=
"special">;
</span></pre>
38 <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>
39 <pre> rule
<span class=
"special"><></span> rule_overall
<span class=
"special">=
</span>
41 <span class=
"special">[
</span>
42 case_p
<span class=
"special"><</span><span class=
"literal">'a'
</span><span class=
"special">>(
</span>parser_a
<span class=
"special">),
</span>
43 case_p
<span class=
"special"><</span><span class=
"literal">'b'
</span><span class=
"special">>(
</span>parser_b
<span class=
"special">),
</span>
44 <span class=
"comment"> // ...
</span>
45 case_p
<span class=
"special"><</span><span class=
"literal">'n'
</span><span class=
"special">>(
</span>parser_n
<span class=
"special">)
</span>
48 <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>
49 <table width=
"80%" border=
"0" align=
"center">
51 <td class=
"note_box"><div align=
"justify"><img src=
"theme/bulb.gif" width=
"13" height=
"18"><strong> Nabialek trick
</strong><br>
53 The
<strong><em><a href=
"techniques.html#nabialek_trick">"Nabialek trick
" </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>
56 <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>
57 <pre> rule
<span class=
"special"><></span> rule_overall
<span class=
"special">=
</span>
59 <span class=
"special">[
</span>
60 case_p
<span class=
"special"><</span><span class=
"literal">'a'
</span><span class=
"special">>(
</span>parser_a
<span class=
"special">),
</span>
61 case_p
<span class=
"special"><</span><span class=
"literal">'b'
</span><span class=
"special">>(
</span>parser_b
<span class=
"special">),
</span>
62 <span class=
"comment"> // ...
</span>
63 case_p
<span class=
"special"><</span><span class=
"literal">'n'
</span><span class=
"special">>(
</span>parser_n
<span class=
"special">),
</span>
64 default_p
<span class=
"special">(
</span>parser_default
<span class=
"special">)
</span>
65 <span class=
"special">]
67 <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>
68 <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>
69 <pre> rule
<span class=
"special"><></span> rule_overall
<span class=
"special">=
</span>
71 <span class=
"special">[
</span>
72 case_p
<span class=
"special"><</span><span class=
"literal">'a'
</span><span class=
"special">>(
</span>parser_a
<span class=
"special">),
</span>
73 case_p
<span class=
"special"><</span><span class=
"literal">'b'
</span><span class=
"special">>(
</span>parser_b
<span class=
"special">),
</span>
74 <span class=
"comment">// ...
</span>
75 case_p
<span class=
"special"><</span><span class=
"literal">'n'
</span><span class=
"special">>(
</span>parser_n
<span class=
"special">),
</span>
77 <span class=
"special">]
</span>
79 <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>
80 <pre> rule
<span class=
"special"><></span> rule_overall
<span class=
"special">=
</span>
81 switch_p
<span class=
"special">(
</span>cond
<span class=
"special">)
</span>
82 <span class=
"special">[
</span>
83 case_p
<span class=
"special"><</span><span class=
"literal">'a'
</span><span class=
"special">>(
</span>parser_a
<span class=
"special">),
</span>
84 case_p
<span class=
"special"><</span><span class=
"literal">'b'
</span><span class=
"special">>(
</span>parser_b
<span class=
"special">),
</span>
85 <span class=
"comment"> // ...
</span>
86 case_p
<span class=
"special"><</span><span class=
"literal">'n'
</span><span class=
"special">>(
</span>parser_n
<span class=
"special">)
</span>
87 <span class=
"special">]
</span>
89 <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>
90 <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>
91 <table width=
"80%" border=
"0" align=
"center">
93 <td class=
"note_box"><p><img src=
"theme/alert.gif" width=
"16" height=
"16"> <tt>BOOST_SPIRIT_SWITCH_CASE_LIMIT
</tt><br>
95 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>
97 <p class=
"style1"><span class=
"comment">// Define these before including switch.hpp
<br>
98 </span><span class=
"preprocessor">#define
</span> BOOST_SPIRIT_SWITCH_CASE_LIMIT
10 </p></td>
104 <td width=
"30"><a href=
"../index.html"><img src=
"theme/u_arr.gif" border=
"0"></a></td>
105 <td width=
"30"><a href=
"select_parser.html"><img src=
"theme/l_arr.gif" border=
"0"></a></td>
106 <td width=
"30"><a href=
"escape_char_parser.html"><img src=
"theme/r_arr.gif" border=
"0"></a></td>
111 <p class=
"copyright">Copyright
© 2003-
2004 Hartmut Kaiser
<br>
113 <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>