Sophie

Sophie

distrib > Mandriva > 9.1 > i586 > by-pkgid > b9ba69a436161613d8fb030c8c726a8e > files > 422

spirit-1.5.1-2mdk.noarch.rpm

<html>
<head>
<title>The Grammar</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="theme/style.css" type="text/css">
</head>

<body>
<table width="100%" border="0" background="theme/bkd2.gif" cellspacing="2">
  <tr> 
    <td width="10"> 
    </td>
    <td width="85%"> 
      <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>The Grammar</b></font>
    </td>
    <td width="112"><a href="http://spirit.sf.net"><img src="theme/spirit.gif" width="112" height="48" align="right" border="0"></a></td>
  </tr>
</table>
<br>
<table border="0">
  <tr>
    <td width="10"></td>
    <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
    <td width="30"><a href="scanner.html"><img src="theme/l_arr.gif" border="0"></a></td>
    <td width="20"><a href="subrules.html"><img src="theme/r_arr.gif" border="0"></a></td>
   </tr>
</table>
<p>The <b>grammar</b> encapsulates a set of rules. The <tt>grammar</tt> class 
  is a protocol base class for all grammars. It is essentially an interface contract. 
  The <tt>grammar</tt> is a template class that is parameterized by its derived 
  class, <tt>DerivedT</tt>, and its context, <tt>ContextT</tt> <a href="rule.html#context"><img src="theme/lens.gif" width="15" height="16" border="0"></a>. 
  The template parameter <tt>ContextT</tt> defaults to <tt>parser_context</tt>, 
  a predefined context that basically does nothing. The <tt>grammar</tt> relies 
  on the template parameter <tt>DerivedT</tt>, a grammar subclass to define the 
  actual rules.</p>
<pre><code><font color="#000000"><span class=identifier>    </span><span class=keyword>template </span><span class=special>
    &lt;
        </span><span class=keyword>typename </span><span class=identifier>DerivedT</span><span class=special>,
        </span><span class=keyword>typename </span><span class=identifier>ContextT </span><span class=special>= </span><span class=identifier>parser_context
    </span><span class=special>&gt;
    </span><span class=keyword>struct </span><span class=identifier>grammar</span><span class=special>;</span></font></code></pre>
<h2>Grammar definition</h2>
<p>A concrete sub-class inheriting from <tt>grammar</tt> is expected to have a 
  nested template class (or struct) named <tt>definition</tt>:</p>
<blockquote>
  <p><img src="theme/bullet.gif" width="13" height="13"> It is a nested template 
    class with a typename <tt>ScannerT</tt> parameter.<br>
    <img src="theme/bullet.gif" width="13" height="13"> Its constructor defines 
    the rules.<br>
    <img src="theme/bullet.gif" width="13" height="13"> Its constructor is passed 
    in a reference to the actual grammar <tt>self</tt>.<br>
    <img src="theme/bullet.gif" width="13" height="13"> It has a member function 
    named <tt>start</tt> that returns a reference to the start <tt>rule</tt>.</p>
</blockquote>
<h2>Grammar skeleton</h2>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>my_grammar </span><span class=special>: </span><span class=keyword>public </span><span class=identifier>grammar</span><span class=special>&lt;</span><span class=identifier>my_grammar</span><span class=special>&gt;
    </span><span class=special>{
        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>ScannerT</span><span class=special>&gt;
        </span><span class=keyword>struct </span><span class=identifier>definition
        </span><span class=special>{
            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt;  </span><span class=identifier>r</span><span class=special>;
            </span><span class=identifier>definition</span><span class=special>(</span><span class=identifier>my_grammar </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>self</span><span class=special>)  </span><span class=special>{ </span><span class=identifier>r </span><span class=special>= </span><span class=comment>/*..define here..*/</span><span class=special>; </span><span class=special>}
            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>start</span><span class=special>() </span><span class=keyword>const </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>r</span><span class=special>; </span><span class=special>}
        </span><span class=special>};
    </span><span class=special>};</span></font></code></pre>
<p>Decoupling the scanner type, and hence iterator, from the rules that form a 
  grammar allows the grammar to be used in different contexts possibly using different 
  scanners/iterators. We don't care what scanner we are dealing with. The user 
  defined <tt>my_grammar</tt> can be instantiated without regard to a scanner 
  type and can be used as a parser using <b>any</b> type of scanner. In short, 
  unlike the rule, the grammar is not tied to a specific scanner type. See <a href="scanner.html#business">&quot;Scanner 
  Business&quot;</a> to see why this is important and to gain further understanding 
  on this scanner-rule coupling problem.</p>
<h2>Instantiating and using my_grammar</h2>
<p>Our grammar above may now be instantiated and put into action:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=identifier>my_grammar </span><span class=identifier>g</span><span class=special>;

    </span><span class=keyword>if </span><span class=special>(</span><span class=identifier>parse</span><span class=special>(</span><span class=identifier>first</span><span class=special>, </span><span class=identifier>last</span><span class=special>, </span><span class=identifier>g</span><span class=special>, </span><span class=identifier>space_p</span><span class=special>).</span><span class=identifier>full</span><span class=special>)
        </span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>"parsing succeeded\n"</span><span class=special>;
    </span><span class=keyword>else
        </span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>"parsing failed\n"</span><span class=special>;</span></font></code></pre>
<p><tt>my_grammar</tt> <b>IS-A </b>parser and can be used anywhere a parser is 
  expected, even referenced by another rule:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=identifier>rule</span><span class=special>&lt;&gt;  </span><span class=identifier>r </span><span class=special>= </span><span class=identifier>g </span><span class=special>&gt;&gt; </span><span class=identifier>str_p</span><span class=special>(</span><span class=string>"cool huh?"</span><span class=special>);</span></font></code></pre>
<h2><a name="full_grammar"></a>Full Grammar Example</h2>
<p>Following our original calculator example, here it is now rewritten using a 
  grammar:</p>
<pre><code><font color="#000000"><span class=special>    </span><span class=keyword>struct </span><span class=identifier>calculator </span><span class=special>: </span><span class=keyword>public </span><span class=identifier>grammar</span><span class=special>&lt;</span><span class=identifier>calculator</span><span class=special>&gt;
    </span><span class=special>{
        </span><span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>typename </span><span class=identifier>ScannerT</span><span class=special>&gt;
        </span><span class=keyword>struct </span><span class=identifier>definition
        </span><span class=special>{
            </span><span class=identifier>definition</span><span class=special>(</span><span class=identifier>calculator </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>self</span><span class=special>)
            </span><span class=special>{
                </span><span class=identifier>group       </span><span class=special>= </span><span class=literal>'(' </span><span class=special>&gt;&gt; </span><span class=identifier>expression </span><span class=special>&gt;&gt; </span><span class=literal>')'</span><span class=special>;
                </span><span class=identifier>factor      </span><span class=special>= </span><span class=identifier>integer </span><span class=special>| </span><span class=identifier>group</span><span class=special>;
                </span><span class=identifier>term        </span><span class=special>= </span><span class=identifier>factor </span><span class=special>&gt;&gt; </span><span class=special>*((</span><span class=literal>'*' </span><span class=special>&gt;&gt; </span><span class=identifier>factor</span><span class=special>) </span><span class=special>| </span><span class=special>(</span><span class=literal>'/' </span><span class=special>&gt;&gt; </span><span class=identifier>factor</span><span class=special>));
                </span><span class=identifier>expression  </span><span class=special>= </span><span class=identifier>term </span><span class=special>&gt;&gt; </span><span class=special>*((</span><span class=literal>'+' </span><span class=special>&gt;&gt; </span><span class=identifier>term</span><span class=special>) </span><span class=special>| </span><span class=special>(</span><span class=literal>'-' </span><span class=special>&gt;&gt; </span><span class=identifier>term</span><span class=special>));
            </span><span class=special>}

            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </span><span class=identifier>expression</span><span class=special>, </span><span class=identifier>term</span><span class=special>, </span><span class=identifier>factor</span><span class=special>, </span><span class=identifier>group</span><span class=special>;

            </span><span class=identifier>rule</span><span class=special>&lt;</span><span class=identifier>ScannerT</span><span class=special>&gt; </span><span class=keyword>const</span><span class=special>&
            </span><span class=identifier>start</span><span class=special>() </span><span class=keyword>const </span><span class=special>{ </span><span class=keyword>return </span><span class=identifier>expression</span><span class=special>; </span><span class=special>}
        </span><span class=special>};
    </span><span class=special>};</span></font></code></pre>
<p><img src="theme/lens.gif" width="15" height="16"> A fullly working example 
  with <a href="semantic_actions.html">semantic actions</a> can be <a href="calc_plain.cpp.html">viewed 
  here</a>. This is part of the Spirit distribution. <br>
  [ See libs/spirit/example/fundamental/calc/calc_plain.cpp ] </p>
<table width="80%" border="0" align="center">
  <tr> 
    <td class="note_box"><img src="theme/lens.gif" width="15" height="16"> <b>self</b><br>
      <br>
      You might notice that the definition of the grammar has a constructor that 
      accepts a const reference to the outer grammar. In the example above, notice 
      that <tt>calculator::definition</tt> takes in a <tt>calculator const&amp; 
      self</tt>. While this is unused in the example above, in many cases, this 
      is very useful. The self argument is the definition's window to the outside 
      world. For example, the calculator class might have a reference to some 
      state information that the definition can update while parsing proceeds 
      through <a href="semantic_actions.html">semantic actions</a>. </td>
  </tr>
</table>
<h2>Grammar Capsules</h2>
<p>As the grammar gets quite complicated, it is a good idea to group parts of 
  the grammar into logical modules. For instance, when writing a language, it 
  might be wise to put expressions and statements into separate grammar capsules. 
  The grammar takes advantage of the encapsulation properties of C++ classes. 
  The declarative nature of classes makes it a perfect fit for the definition 
  of grammars. Since the grammar is nothing more than a class declaration we can 
  conveniently publish it in header files. The idea is that once written and fully 
  tested, a grammar can be reused in many contexts. We now have the notion of 
  grammar libraries.</p>
<h2>Reentrancy and multithreading</h2>
<p>An instance of a grammar may be used in different places multiple times without 
  any problem. The implementation is tuned to allow this at the expense of some 
  overhead. However, we can save considerable cycles and bytes if we are certain 
  that a grammar will only have a single instance. If this is desired, simply 
  define SPIRIT_SINGLE_GRAMMAR_INSTANCE before including any spirit header files.</p>
<p><font face="Courier New, Courier, mono"><code><span class="preprocessor">#define</span></code></font><span class="preprocessor"><code><font face="Courier New, Courier, mono"> 
  </font><tt>SPIRIT_SINGLE_GRAMMAR_INSTANCE</tt></code></span> <br>
  <br>
  On the other hand, if a grammar is intended to be used in multithreaded code, 
  we should then define SPIRIT_THREADSAFE before including any spirit header files.<br>
  <br>
  <font face="Courier New, Courier, mono"><span class="preprocessor">#define</span></font> 
  <span class="preprocessor"><tt>SPIRIT_THREADSAFE</tt></span></p>
<table border="0">
  <tr> 
    <td width="10"></td>
    <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
    <td width="30"><a href="scanner.html"><img src="theme/l_arr.gif" border="0"></a></td>
    <td width="20"><a href="subrules.html"><img src="theme/r_arr.gif" border="0"></a></td>
  </tr>
</table>
<br>
<hr size="1">
<p class="copyright">Copyright &copy; 1998-2002 Joel de Guzman<br>
  <br>
  <font size="2">Permission to copy, use, modify, sell and distribute this document 
  is granted provided this copyright notice appears in all copies. This document 
  is provided &quot;as is&quot; without express or implied warranty, and with 
  no claim as to its suitability for any purpose. </font> </p>
<p>&nbsp;</p>
</body>
</html>