<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[boost::spirit mehrere Fragen]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich beschäftige mich nun seit kurzer Zeit mit boost::spirit, um einen recht einfachen Parser zu realisieren. Das Parsen an sich funktioniert schon so wie es soll, doch manches ist mir auch nach einigem lesen nicht ganz klar geworden. Ganz unten steht der aktuell gesamte Code und ein Beispiel einer Inputdatei.</p>
<p>1. Meine Regel &quot;object&quot;: Ich möchte sicherstellen, dass die Reihenfolge der Zuweisungen von bore, length und friction beliebig ist, aber trotzdem alle drei vorkommen müssen. Anfangs dachte ich, dazu gäbe es den Operator &amp;. Explizit:</p>
<pre><code class="language-cpp">object = *(nodes &gt;&gt; &quot;{&quot; &gt;&gt; (((&quot;length&quot; &gt;&gt; assignment) &amp; (&quot;bore&quot; &gt;&gt; assignment) &amp; (&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; &quot;}&quot;);
</code></pre>
<p>Meiner Meinung nach sollte das heißen: Ich erwarte 0 bis unendlich viele Objekte der Art: nodes, gefolgt von length=assignment, bore=assignment und friction=assignment in beliebiger Reihenfolge (das Ganze in {}). Allerdings funktioniert das so nicht. Stattdessen gebe ich stumpf jede Möglichkeit einzelnd an. Das muss ja wohl irgendwie anders gehen.</p>
<p>2. Mein angegebenes Beispiel wird zwar komplett geparst (pi.length ist 66, das sind alle Zeichen). Trotzdem ist pi.full false und mein Output damit &quot;parsing data partially&quot;. Ich würde gern wissen, warum das so ist.</p>
<p>3. Der Operator () im struct save (der Name ist in Anbetracht seiner Funktion im Moment noch etwas irreleitend) innerhalb meiner Grammatik soll mir so wie es da steht einfach den übergenenen Double ausgeben. Angewandt wird er auf den real_p in der Regel assignment. D.h. im konkreten Beispiel wird 1,2,3,4,5,6 ausgegeben, was auch funktioniert.<br />
Wie der Name vermuten lässt, sollte save aber eigentlich dazu da sein, meine Werte in eine im Moment noch nicht vorhandene Datenstruktur zu speichern, der Einfachheit halber von mir aus erst mal in einen vector o.ä. Wie kann ich das in einer Methode meiner Klasse open_file realisieren? Ich habe mir grundsätzlich sowas vorgestellt, aber keine Idee, wie ich es umsetzen kann.</p>
<pre><code class="language-cpp">vector&lt;double&gt; save(){
  vector&lt;double&gt; v;
  //An der Stelle auf irgendeine Art und Weise die d's aus meiner Grammatik abholen und in v schreiben
  return v;
}
</code></pre>
<p>Hoffentlich findet sich jemand mit mehr Ahnung als ich es habe. Ich wäre sehr verbunden <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Beispiel korrekter Syntax:</p>
<pre><code>1-&gt;2{
bore=1;
length=2;
friction=3;
}
2-&gt;3{
length=4;
bore=5;
friction=6;
}
</code></pre>
<pre><code class="language-cpp">#include &lt;boost/spirit.hpp&gt;

#include &lt;iostream&gt;
#include &lt;sstream&gt;
#include &lt;fstream&gt;
#include &lt;vector&gt;

using namespace boost::spirit;
using namespace std;

struct pipenetwork_grammar : public grammar&lt;pipenetwork_grammar&gt; {
  struct save{
    void operator()(const double d) const {
      cout &lt;&lt; d &lt;&lt; endl;
    }
  }; 

  template &lt;typename Scanner&gt;
  struct definition { 
    rule&lt;Scanner&gt; object, nodes, assignment, identifier, value, coordinates; 
    definition(const pipenetwork_grammar &amp;self) {
      object = *(nodes &gt;&gt; &quot;{&quot; &gt;&gt; (((&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment))
		               |  ((&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment))
		               |  ((&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment))
		               |  ((&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment))
		               |  ((&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment))
			       |  ((&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment)))
                &gt;&gt; &quot;}&quot;);
      nodes = int_p &gt;&gt; &quot;-&gt;&quot; &gt;&gt; int_p; 
      assignment = &quot;=&quot; &gt;&gt; real_p[save()] &gt;&gt; &quot;;&quot;;
    }
    const rule&lt;Scanner&gt; &amp;start() { 
      return object; 
    } 
  };
};

class open_file{
private:
  ifstream file; 
  ostringstream ss; 
  string data; 
  pipenetwork_grammar g; 
public:
  open_file();
  open_file(char *filename){
    open(filename);
  }
  void open(char *filename){
    file.open(filename);
    ss &lt;&lt; file.rdbuf(); 
    data = ss.str();
    parse_info&lt;&gt; pi = parse(data.c_str(), g, space_p);
    if (pi.hit) { 
	if (pi.full) 
	  cout &lt;&lt; &quot;parsing all data successfully&quot; &lt;&lt; endl; 
	else 
	  cout &lt;&lt; &quot;parsing data partially&quot; &lt;&lt; endl;
	cout &lt;&lt; pi.length &lt;&lt; &quot; characters parsed&quot; &lt;&lt; endl; 
      } 
    else 
      cout &lt;&lt; &quot;parsing failed; stopped at '&quot; &lt;&lt; pi.stop &lt;&lt; &quot;'&quot; &lt;&lt; endl;
  }
};

int main(int argc, char *argv[]){ 
  open_file pipenetwork_file(argv[1]);
  return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/300855/boost-spirit-mehrere-fragen</link><generator>RSS for Node</generator><lastBuildDate>Wed, 12 Aug 2026 15:22:18 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/300855.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 12 Mar 2012 19:25:50 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 19:25:50 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich beschäftige mich nun seit kurzer Zeit mit boost::spirit, um einen recht einfachen Parser zu realisieren. Das Parsen an sich funktioniert schon so wie es soll, doch manches ist mir auch nach einigem lesen nicht ganz klar geworden. Ganz unten steht der aktuell gesamte Code und ein Beispiel einer Inputdatei.</p>
<p>1. Meine Regel &quot;object&quot;: Ich möchte sicherstellen, dass die Reihenfolge der Zuweisungen von bore, length und friction beliebig ist, aber trotzdem alle drei vorkommen müssen. Anfangs dachte ich, dazu gäbe es den Operator &amp;. Explizit:</p>
<pre><code class="language-cpp">object = *(nodes &gt;&gt; &quot;{&quot; &gt;&gt; (((&quot;length&quot; &gt;&gt; assignment) &amp; (&quot;bore&quot; &gt;&gt; assignment) &amp; (&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; &quot;}&quot;);
</code></pre>
<p>Meiner Meinung nach sollte das heißen: Ich erwarte 0 bis unendlich viele Objekte der Art: nodes, gefolgt von length=assignment, bore=assignment und friction=assignment in beliebiger Reihenfolge (das Ganze in {}). Allerdings funktioniert das so nicht. Stattdessen gebe ich stumpf jede Möglichkeit einzelnd an. Das muss ja wohl irgendwie anders gehen.</p>
<p>2. Mein angegebenes Beispiel wird zwar komplett geparst (pi.length ist 66, das sind alle Zeichen). Trotzdem ist pi.full false und mein Output damit &quot;parsing data partially&quot;. Ich würde gern wissen, warum das so ist.</p>
<p>3. Der Operator () im struct save (der Name ist in Anbetracht seiner Funktion im Moment noch etwas irreleitend) innerhalb meiner Grammatik soll mir so wie es da steht einfach den übergenenen Double ausgeben. Angewandt wird er auf den real_p in der Regel assignment. D.h. im konkreten Beispiel wird 1,2,3,4,5,6 ausgegeben, was auch funktioniert.<br />
Wie der Name vermuten lässt, sollte save aber eigentlich dazu da sein, meine Werte in eine im Moment noch nicht vorhandene Datenstruktur zu speichern, der Einfachheit halber von mir aus erst mal in einen vector o.ä. Wie kann ich das in einer Methode meiner Klasse open_file realisieren? Ich habe mir grundsätzlich sowas vorgestellt, aber keine Idee, wie ich es umsetzen kann.</p>
<pre><code class="language-cpp">vector&lt;double&gt; save(){
  vector&lt;double&gt; v;
  //An der Stelle auf irgendeine Art und Weise die d's aus meiner Grammatik abholen und in v schreiben
  return v;
}
</code></pre>
<p>Hoffentlich findet sich jemand mit mehr Ahnung als ich es habe. Ich wäre sehr verbunden <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Beispiel korrekter Syntax:</p>
<pre><code>1-&gt;2{
bore=1;
length=2;
friction=3;
}
2-&gt;3{
length=4;
bore=5;
friction=6;
}
</code></pre>
<pre><code class="language-cpp">#include &lt;boost/spirit.hpp&gt;

#include &lt;iostream&gt;
#include &lt;sstream&gt;
#include &lt;fstream&gt;
#include &lt;vector&gt;

using namespace boost::spirit;
using namespace std;

struct pipenetwork_grammar : public grammar&lt;pipenetwork_grammar&gt; {
  struct save{
    void operator()(const double d) const {
      cout &lt;&lt; d &lt;&lt; endl;
    }
  }; 

  template &lt;typename Scanner&gt;
  struct definition { 
    rule&lt;Scanner&gt; object, nodes, assignment, identifier, value, coordinates; 
    definition(const pipenetwork_grammar &amp;self) {
      object = *(nodes &gt;&gt; &quot;{&quot; &gt;&gt; (((&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment))
		               |  ((&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment))
		               |  ((&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment))
		               |  ((&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment))
		               |  ((&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment))
			       |  ((&quot;friction&quot; &gt;&gt; assignment) &gt;&gt; (&quot;length&quot; &gt;&gt; assignment) &gt;&gt; (&quot;bore&quot; &gt;&gt; assignment)))
                &gt;&gt; &quot;}&quot;);
      nodes = int_p &gt;&gt; &quot;-&gt;&quot; &gt;&gt; int_p; 
      assignment = &quot;=&quot; &gt;&gt; real_p[save()] &gt;&gt; &quot;;&quot;;
    }
    const rule&lt;Scanner&gt; &amp;start() { 
      return object; 
    } 
  };
};

class open_file{
private:
  ifstream file; 
  ostringstream ss; 
  string data; 
  pipenetwork_grammar g; 
public:
  open_file();
  open_file(char *filename){
    open(filename);
  }
  void open(char *filename){
    file.open(filename);
    ss &lt;&lt; file.rdbuf(); 
    data = ss.str();
    parse_info&lt;&gt; pi = parse(data.c_str(), g, space_p);
    if (pi.hit) { 
	if (pi.full) 
	  cout &lt;&lt; &quot;parsing all data successfully&quot; &lt;&lt; endl; 
	else 
	  cout &lt;&lt; &quot;parsing data partially&quot; &lt;&lt; endl;
	cout &lt;&lt; pi.length &lt;&lt; &quot; characters parsed&quot; &lt;&lt; endl; 
      } 
    else 
      cout &lt;&lt; &quot;parsing failed; stopped at '&quot; &lt;&lt; pi.stop &lt;&lt; &quot;'&quot; &lt;&lt; endl;
  }
};

int main(int argc, char *argv[]){ 
  open_file pipenetwork_file(argv[1]);
  return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2191013</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191013</guid><dc:creator><![CDATA[g0nz0]]></dc:creator><pubDate>Mon, 12 Mar 2012 19:25:50 GMT</pubDate></item><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 19:39:37 GMT]]></title><description><![CDATA[<p>Sofern du nicht eine sehr alte Version von Boost verwendest, sollte dich dein Compiler warnen, dass du Spirit 1 verwendest, also die ganz alte Version. Wenn das so gewollt ist, kannst du ans Ende der Definition der object-Regel</p>
<pre><code class="language-cpp">&gt;&gt; !end_p
</code></pre>
<p>anfügen. Ich rate dir aber ganz ernsthaft dazu, Neuentwicklungen mit Spirit 2 anzufangen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2191016</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191016</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Mon, 12 Mar 2012 19:39:37 GMT</pubDate></item><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 19:48:31 GMT]]></title><description><![CDATA[<p>Danke schon mal! Dein Vorschlag behebt auf jeden Fall schon mal Problem Nummer 2.</p>
<p>Da bin ich wohl auf ein altes Tutorial gestoßen, ohne dass es mir aufgefallen ist. Hm, ich muss mal herausfinden, welche Boost Version auf unserem Uni-Cluster verwendet wird, gehe aber mal von einer recht neuen aus. Sollte hier aber noch jemand um die Ecke kommen und vor allem eine Antwort oder Gedankenanstoß für Frage 3 haben, würde ich mich trotzdem freuen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2191017</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191017</guid><dc:creator><![CDATA[g0nz0]]></dc:creator><pubDate>Mon, 12 Mar 2012 19:48:31 GMT</pubDate></item><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 21:33:47 GMT]]></title><description><![CDATA[<p>Doku zu Spirit 2 findet sich <a href="http://www.boost.org/doc/libs/1_49_0/libs/spirit/doc/html/index.html" rel="nofollow">hier</a>.</p>
<p>Deine Grammatik denke ich mir ungefähr so:</p>
<pre><code class="language-cpp">#include &lt;boost/spirit/include/qi.hpp&gt;
#include &lt;boost/fusion/adapted/std_pair.hpp&gt;
#include &lt;boost/fusion/include/adapt_struct.hpp&gt;

#include &lt;iostream&gt;
#include &lt;map&gt;
#include &lt;sstream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;

// Vermutlich sinnvoll: boost::spirit::qi::symbols benutzen und
// hier dann statt std::string eine enum als Schlüsseltypen.
typedef std::map&lt;std::string, double&gt; property_map_t;

struct edge {
  int from;
  int to;

  property_map_t properties;
};

BOOST_FUSION_ADAPT_STRUCT(edge,
                          (int, from)
                          (int, to)
                          (property_map_t, properties))

class edge_grammar
  : public boost::spirit::qi::grammar&lt;std::string::const_iterator,
                                      edge(),
                                      boost::spirit::qi::standard::space_type&gt;
{
public:
  edge_grammar() : edge_grammar::base_type(object) {
    namespace qi = boost::spirit::qi;

    object         = qi::int_ &gt;&gt; &quot;-&gt;&quot; &gt;&gt; qi::int_ &gt;&gt; '{' &gt;&gt; property_list &gt;&gt; '}';

    property_list  = *property;
    property       = property_name &gt;&gt; '=' &gt;&gt; property_value &gt;&gt; ';';

    property_name  = qi::string(&quot;length&quot;) | qi::string(&quot;friction&quot;) | qi::string(&quot;bore&quot;);
    property_value = qi::double_;
  }

private:
  typedef std::string::const_iterator iterator_t;
  typedef boost::spirit::qi::standard::space_type space_t;

  // Metafunktion nur, um die Verweise auf iterator_t und space_t zentral zu haben.
  template&lt;typename T&gt; struct rule_type {
    typedef boost::spirit::qi::rule&lt;iterator_t, T(), space_t&gt; type;
  };

  rule_type&lt;edge                           &gt;::type object;
  rule_type&lt;property_map_t                 &gt;::type property_list;
  rule_type&lt;std::pair&lt;std::string, double&gt; &gt;::type property;
  rule_type&lt;std::string                    &gt;::type property_name;
  rule_type&lt;double                         &gt;::type property_value;
};

int main() {
  edge_grammar edge_;
  std::string data =
    &quot;1 -&gt; 2 { length = 1.2; bore = 2.3; friction = 3.4; }&quot;
    &quot;2 -&gt; 3 { bore = 4; length = 5; friction = 6; }&quot;
    ;

  std::string::const_iterator first = data.begin();
  std::string::const_iterator last  = data.end  ();
  std::vector&lt;edge&gt; edges;

  bool r = boost::spirit::qi::phrase_parse(first, last, *edge_, boost::spirit::qi::standard::space, edges);

  if(r &amp;&amp; first == last) {
    for(std::vector&lt;edge&gt;::const_iterator i = edges.begin(); i != edges.end(); ++i) {
      std::cout &lt;&lt; &quot;Von &quot; &lt;&lt; i-&gt;from &lt;&lt; &quot; nach &quot; &lt;&lt; i-&gt;to &lt;&lt; &quot;:\n\n&quot;;

      for(property_map_t::const_iterator p = i-&gt;properties.begin(); p != i-&gt;properties.end(); ++p) {
        std::cout &lt;&lt; p-&gt;first &lt;&lt; &quot; = &quot; &lt;&lt; p-&gt;second &lt;&lt; '\n';
      }

      std::cout &lt;&lt; '\n';
    }
  }
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2191031</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191031</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Mon, 12 Mar 2012 21:33:47 GMT</pubDate></item><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 21:52:09 GMT]]></title><description><![CDATA[<p>Wow, damit hab ich gar nicht gerechnet. Vielen, vielen Dank!!! Ich bin gerade mal drübergeflogen und habs kurz ausprobiert und es funktioniert wunderbar!<br />
Morgen werde ich mal versuchen, das alles zu verstehen und melde mich vielleicht noch mal bei Verständnisfragen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2191035</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191035</guid><dc:creator><![CDATA[g0nz0]]></dc:creator><pubDate>Mon, 12 Mar 2012 21:52:09 GMT</pubDate></item><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 22:51:32 GMT]]></title><description><![CDATA[<p>Da fehlt aber noch ein Check, dass alle drei Parameter angegeben wurden. In den meisten Grammatiken muss man das entweder von Hand kodieren (6 Fallunterscheidungen wären das in deinem Fall), oder man macht das im Anschluss. Letzteres ist meist einfacher, da man mit weniger Code auskommt.</p>
<p>Oder für Faule: du definierst fortgelassene Attribute zu einem standardisierten Wert <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2191042</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191042</guid><dc:creator><![CDATA[C++ler]]></dc:creator><pubDate>Mon, 12 Mar 2012 22:51:32 GMT</pubDate></item><item><title><![CDATA[Reply to boost::spirit mehrere Fragen on Mon, 12 Mar 2012 23:06:49 GMT]]></title><description><![CDATA[<p>Ich würde das bei Bedarf hinterher prüfen; meiner Ansicht nach handelt es sich dabei nicht um einen Syntaxfehler, also ist der Parser der falsche Ort für seine Behandlung. Kirche, Dorf und so.</p>
<p>Was den Code angeht, schau in die Dokus zu Boost.Spirit und Boost.Fusion. Wenn man verstanden hat, was Boost.Fusion soll, ist die Parser-Attributierung in Boost.Spirit ziemlich straightforward, und dann sollte dieses Beispiel dich nicht mehr vor allzu große Verständnisprobleme stellen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2191043</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2191043</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Mon, 12 Mar 2012 23:06:49 GMT</pubDate></item></channel></rss>