<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Spirit: parsing without leaving C++</title>
	<atom:link href="http://blog.davber.com/2006/07/06/the-spirit-of-parsing/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.davber.com/2006/07/06/the-spirit-of-parsing/</link>
	<description>Functional functional programming - Haskell, Ruby, Erlang, Scala...</description>
	<lastBuildDate>Mon, 04 Jan 2010 21:38:57 -0500</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: davber</title>
		<link>http://blog.davber.com/2006/07/06/the-spirit-of-parsing/comment-page-1/#comment-537</link>
		<dc:creator>davber</dc:creator>
		<pubDate>Tue, 26 Feb 2008 17:45:54 +0000</pubDate>
		<guid isPermaLink="false">http://blog.davber.com/?p=6#comment-537</guid>
		<description>Joel,

I should change the snippets to include a reference to the license type used. Till then, I grant an MIT license to the above snippet (is this enough?) For completeness (or at least self-containment...), I include the full snippet herein, with the license reference added.

Thanks,

David

---------------------------------------------

/*
 
File: parse_arith.cpp
Author: David Bergman
 
This file describes a simple arithmetic language
using Boost.Spirit.
 
It does so by creating an AST and then implementing
an evaluating visitor for such nodes. Not really a
visitor, since it handles the traversal itself, but
you get the point...

License Information (MIT License):

Copyright (c) 2006-2008 David Bergman

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &quot;Software&quot;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/
 
#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;map&gt;
#include &lt;boost/lexical_cast.hpp&gt;
#include &lt;boost/function.hpp&gt;
#include &lt;boost/spirit/core.hpp&gt;
#include &lt;boost/spirit/tree/ast.hpp&gt;
 
using namespace std;
using namespace boost::spirit;
using namespace boost;
 
typedef tree_match&lt;const char*&gt; TreeMatch;
typedef TreeMatch::tree_iterator TreeIter;
 
// We use Abstract Syntax Trees
 
struct expression : public grammar&lt;expression&gt;
{
  // Need explicit identifiers to switch properly
  // when evaluating the AST
  static const int factorID = 1;
  static const int termID = 2;
  static const int expID = 3;
 
  // Meta function from scanner type to a proper
  // rule type
  template&lt;typename ScannerT&gt;
  struct definition
  {
    rule&lt;ScannerT, parser_context&lt;&gt;,
	 parser_tag&lt;expID&gt; &gt; exp_p;
    rule&lt;ScannerT, parser_context&lt;&gt;,
	 parser_tag&lt;factorID&gt; &gt; factor_p;
    rule&lt;ScannerT, parser_context&lt;&gt;,
	 parser_tag&lt;termID&gt; &gt; term_p;
    definition(const expression&amp; self) {
      factor_p =
	leaf_node_d[int_p] &#124;
	inner_node_d[&#039;(&#039; &gt;&gt; exp_p &gt;&gt; &#039;)&#039;];
      term_p =
	factor_p &gt;&gt; *(root_node_d[ch_p(&#039;*&#039;)] &gt;&gt;
		      factor_p
		      &#124;
		      root_node_d[ch_p(&#039;/&#039;)] &gt;&gt;
		      factor_p);
      exp_p = term_p &gt;&gt;
	*(root_node_d[ch_p(&#039;+&#039;)] &gt;&gt; term_p &#124;
	  root_node_d[ch_p(&#039;-&#039;)] &gt;&gt; term_p);
      BOOST_SPIRIT_DEBUG_RULE(factor_p);
      BOOST_SPIRIT_DEBUG_RULE(term_p);
      BOOST_SPIRIT_DEBUG_RULE(exp_p);
    }

    const rule&lt;ScannerT, parser_context&lt;&gt;,
	       parser_tag&lt;expID&gt; &gt;&amp;
    start()
      const {
      return exp_p;
    }
  };
};
 
// Map operators to operations
 
static map&lt;char, function&lt;int (int, int)&gt; &gt; op;
 
// The evaluation function for the ASTs
 
static int eval_expression(const TreeIter&amp; i);
 
int evaluate(tree_parse_info&lt;&gt; match)
{
  return eval_expression(match.trees.begin());
}
 
int eval_expression(const TreeIter&amp; i)
{
  return
    (i-&gt;value.id() == expression::factorID) ?
    // Simple numeric literal
    lexical_cast&lt;int&gt;(string(i-&gt;value.begin(),
			     i-&gt;value.end())) :
    // A dyadic operation
    op[*i-&gt;value.begin()]
    (eval_expression(i-&gt;children.begin()),
     eval_expression(i-&gt;children.begin() + 1));
}
 
int main(int argc, char* argv[])
{
  // Init the operations
 
  op[&#039;*&#039;] = multiplies&lt;int&gt;();
  op[&#039;/&#039;] = divides&lt;int&gt;();
  op[&#039;+&#039;] = plus&lt;int&gt;();
  op[&#039;-&#039;] = minus&lt;int&gt;();
 
  const string input(argv[1]);
  expression my_exp;
  tree_parse_info&lt;const char*&gt; tree =
    ast_parse(input.c_str(), my_exp);
  if (tree.full) {
    cout &lt;&lt; &quot;result is &quot; &lt;&lt; evaluate(tree)
	 &lt;&lt; endl;
  }
}</description>
		<content:encoded><![CDATA[<p>Joel,</p>
<p>I should change the snippets to include a reference to the license type used. Till then, I grant an MIT license to the above snippet (is this enough?) For completeness (or at least self-containment&#8230;), I include the full snippet herein, with the license reference added.</p>
<p>Thanks,</p>
<p>David</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>/*</p>
<p>File: parse_arith.cpp<br />
Author: David Bergman</p>
<p>This file describes a simple arithmetic language<br />
using Boost.Spirit.</p>
<p>It does so by creating an AST and then implementing<br />
an evaluating visitor for such nodes. Not really a<br />
visitor, since it handles the traversal itself, but<br />
you get the point&#8230;</p>
<p>License Information (MIT License):</p>
<p>Copyright (c) 2006-2008 David Bergman</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy<br />
of this software and associated documentation files (the &#8220;Software&#8221;), to deal<br />
in the Software without restriction, including without limitation the rights<br />
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell<br />
copies of the Software, and to permit persons to whom the Software is<br />
furnished to do so, subject to the following conditions:</p>
<p>THE SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br />
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br />
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE<br />
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br />
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,<br />
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br />
SOFTWARE.</p>
<p>*/</p>
<p>#include <string><br />
#include <iostream><br />
#include<br />
<map>
#include <boost /lexical_cast.hpp><br />
#include </boost><boost /function.hpp><br />
#include </boost><boost /spirit/core.hpp><br />
#include </boost><boost /spirit/tree/ast.hpp></p>
<p>using namespace std;<br />
using namespace boost::spirit;<br />
using namespace boost;</p>
<p>typedef tree_match<const char*> TreeMatch;<br />
typedef TreeMatch::tree_iterator TreeIter;</p>
<p>// We use Abstract Syntax Trees</p>
<p>struct expression : public grammar<expression><br />
{<br />
  // Need explicit identifiers to switch properly<br />
  // when evaluating the AST<br />
  static const int factorID = 1;<br />
  static const int termID = 2;<br />
  static const int expID = 3;</p>
<p>  // Meta function from scanner type to a proper<br />
  // rule type<br />
  template<typename ScannerT><br />
  struct definition<br />
  {<br />
    rule<scannert , parser_context<>,<br />
	 parser_tag<expid> > exp_p;<br />
    rule<scannert , parser_context<>,<br />
	 parser_tag<factorid> > factor_p;<br />
    rule<scannert , parser_context<>,<br />
	 parser_tag<termid> > term_p;<br />
    definition(const expression&#038; self) {<br />
      factor_p =<br />
	leaf_node_d[int_p] |<br />
	inner_node_d['(' >> exp_p >> ')'];<br />
      term_p =<br />
	factor_p >> *(root_node_d[ch_p('*')] >><br />
		      factor_p<br />
		      |<br />
		      root_node_d[ch_p('/')] >><br />
		      factor_p);<br />
      exp_p = term_p >><br />
	*(root_node_d[ch_p('+')] >> term_p |<br />
	  root_node_d[ch_p('-')] >> term_p);<br />
      BOOST_SPIRIT_DEBUG_RULE(factor_p);<br />
      BOOST_SPIRIT_DEBUG_RULE(term_p);<br />
      BOOST_SPIRIT_DEBUG_RULE(exp_p);<br />
    }</p>
<p>    const rule<scannert , parser_context<>,<br />
	       parser_tag<expid> >&#038;<br />
    start()<br />
      const {<br />
      return exp_p;<br />
    }<br />
  };<br />
};</p>
<p>// Map operators to operations</p>
<p>static map<char , function<int (int, int)> > op;</p>
<p>// The evaluation function for the ASTs</p>
<p>static int eval_expression(const TreeIter&#038; i);</p>
<p>int evaluate(tree_parse_info<> match)<br />
{<br />
  return eval_expression(match.trees.begin());<br />
}</p>
<p>int eval_expression(const TreeIter&#038; i)<br />
{<br />
  return<br />
    (i->value.id() == expression::factorID) ?<br />
    // Simple numeric literal<br />
    lexical_cast<int>(string(i->value.begin(),<br />
			     i->value.end())) :<br />
    // A dyadic operation<br />
    op[*i->value.begin()]<br />
    (eval_expression(i->children.begin()),<br />
     eval_expression(i->children.begin() + 1));<br />
}</p>
<p>int main(int argc, char* argv[])<br />
{<br />
  // Init the operations</p>
<p>  op['*'] = multiplies</int><int>();<br />
  op['/'] = divides</int><int>();<br />
  op['+'] = plus</int><int>();<br />
  op['-'] = minus</int><int>();</p>
<p>  const string input(argv[1]);<br />
  expression my_exp;<br />
  tree_parse_info<const char*> tree =<br />
    ast_parse(input.c_str(), my_exp);<br />
  if (tree.full) {<br />
    cout << &#8220;result is &#8221; << evaluate(tree)<br />
	 << endl;<br />
  }<br />
}</const></int></char></expid></scannert></termid></scannert></factorid></scannert></expid></scannert></typename></expression></const></boost></map>
<p></iostream></string></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: jdy</title>
		<link>http://blog.davber.com/2006/07/06/the-spirit-of-parsing/comment-page-1/#comment-536</link>
		<dc:creator>jdy</dc:creator>
		<pubDate>Tue, 26 Feb 2008 16:59:00 +0000</pubDate>
		<guid isPermaLink="false">http://blog.davber.com/?p=6#comment-536</guid>
		<description>David,

I adjusted the grammar to support exponentiation and negation which are both right-to-left.  I also added expect clauses to get better information on why a parse fails.  Here is the new grammar:

      factor_p =  // numbers or parentheticals:
          leaf_node_d[ureal_p] 
        &#124; (inner_node_d[&#039;(&#039; &gt;&gt; expectexpression(start_p) &gt;&gt; expectclose(ch_p(&#039;)&#039;))]);
      power_p = // exponentials (right-to-left)
        (factor_p &gt;&gt; root_node_d[ch_p(&#039;^&#039;)]) &gt;&gt; expectexpression(unary_p) &#124; factor_p;
      unary_p = // unary operators (right-to-left)
        (root_node_d[ch_p(&#039;-&#039;)]) &gt;&gt; expectexpression(unary_p) &#124; power_p;
      term_p =  // multiplicatives (left-to-right) 
        unary_p &gt;&gt; ( *(root_node_d[ch_p(&#039;x&#039;)&#124;&#039;/&#039;] &gt;&gt; expectexpression(unary_p)) ) ;
      exp_p =   // additives (left-to-right)
        term_p &gt;&gt; *(root_node_d[ch_p(&#039;+&#039;)&#124;&#039;-&#039;] &gt;&gt; expectexpression(term_p));
      start_p = expectexpression(exp_p);

Would you be willing to release this code into a boost, GPL, or MIT style license?  I&#039;d like to use it in a class and put it on a course website.

ps.  I posted a similar comment, but it didn&#039;t post so resubmitting.

Thanks,

Joel</description>
		<content:encoded><![CDATA[<p>David,</p>
<p>I adjusted the grammar to support exponentiation and negation which are both right-to-left.  I also added expect clauses to get better information on why a parse fails.  Here is the new grammar:</p>
<p>      factor_p =  // numbers or parentheticals:<br />
          leaf_node_d[ureal_p]<br />
        | (inner_node_d['(' &gt;&gt; expectexpression(start_p) &gt;&gt; expectclose(ch_p(')'))]);<br />
      power_p = // exponentials (right-to-left)<br />
        (factor_p &gt;&gt; root_node_d[ch_p('^')]) &gt;&gt; expectexpression(unary_p) | factor_p;<br />
      unary_p = // unary operators (right-to-left)<br />
        (root_node_d[ch_p('-')]) &gt;&gt; expectexpression(unary_p) | power_p;<br />
      term_p =  // multiplicatives (left-to-right)<br />
        unary_p &gt;&gt; ( *(root_node_d[ch_p('x')|'/'] &gt;&gt; expectexpression(unary_p)) ) ;<br />
      exp_p =   // additives (left-to-right)<br />
        term_p &gt;&gt; *(root_node_d[ch_p('+')|'-'] &gt;&gt; expectexpression(term_p));<br />
      start_p = expectexpression(exp_p);</p>
<p>Would you be willing to release this code into a boost, GPL, or MIT style license?  I&#8217;d like to use it in a class and put it on a course website.</p>
<p>ps.  I posted a similar comment, but it didn&#8217;t post so resubmitting.</p>
<p>Thanks,</p>
<p>Joel</p>
]]></content:encoded>
	</item>
</channel>
</rss>

