<?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[dickes designproblem]]></title><description><![CDATA[<p>ich arbeite ja mit boost::spirit, und ich wollte das konzept irgendwie mit klassen in einklang bringen, aber irgendwie scheitere ich ziemlich, darüber sind auchs chon ein paar tränen und jede menge schweiß geflossen(ergo ich hab darüber aufm hometrainer nachgedacht :D) das problem sind keine fehlermeldungen, sondern dass ich es nicht schaffe die instanz einer klasse an die &quot;informationen verarbeitende stellen&quot; zu bringen,dh klassen sind nicht gut mit spirit in einklang zu bringen, aber zuerst etwas unausgegorenen code:</p>
<pre><code class="language-cpp">//ich brauche hier die functoren, da spirit keine methoden annimmt.
template&lt;class Type&gt;
class sendChar{
	private:
		typedef void (Type::*function)(char);
		Type&amp; classPointer;
		function functionPointer;
		char sign;
	public:
		sendChar(Type&amp; instance,function pointer,char signToSend):classPointer(instance),functionPointer(pointer),sign(signToSend){}
		//der op ist so von spirit vorgegeben, deshalb dieser umweg über den ctor
                void operator()(char const*, char const*)const{
			(classPointer.*functionPointer)(sign);
		}

};
template&lt;class Type,class numberType&gt;
class SendNumber{
	private:
		typedef void (Type::*function)(numberType);
		Type&amp; classPointer;
		function functionPointer;
	public:
		SendNumber(Type&amp; instance,function pointer):classPointer(instance),functionPointer(pointer){}
                void operator()(numberType number)const{
			(classPointer.*functionPointer)(number);
		}
};
//hier ist meine &quot;verarbeitende klasse&quot;
class Interpreter{
public:
	void sendSign(char a){
		//hier werden die werte bearbeitet
	}
	void sendDouble(double value){
		//hier werden die doubles verarbeitet
	}
};

//die formd er klasse sit von spirit so vorgegeben, definition ist der einzige benutzte teil, ich hab deshalb keine chance von aussen irgendeine instanz reinzuschmuggeln
struct calculation:public boost::spirit::grammar&lt;calculation&gt;{
	template &lt;typename ScannerT&gt;
	struct definition{
		Interpreter interpreter;
		boost::spirit::subrule&lt;0&gt; real;

		boost::spirit::subrule&lt;1&gt; expression;
		boost::spirit::subrule&lt;2&gt; term;
		boost::spirit::subrule&lt;3&gt; group;
		boost::spirit::subrule&lt;4&gt; summand;

		boost::spirit::rule&lt;ScannerT&gt; first;
		definition(calculation const&amp; self){
                        //die grammatik ansich
			first=
			(
				expression=term|real,
				term=
					 summand
					 &gt;&gt;*(		('+'&gt;&gt;summand)[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'+')]
//hier wird der functor dann benutzt, wenn der parser bis zum op[] erfolgreich war, wird der functor aufgerufen
						|		('-'&gt;&gt;summand)[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'-')]
						),
				summand=
						(real|group)
						&gt;&gt;*(	('*'&gt;&gt;(real|group))[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'*')]
						|		('/'&gt;&gt;(real|group))[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'/')]
						),
				group='('&gt;&gt;term&gt;&gt;')',

				real=boost::spirit::real_p[SendNumber&lt;Interpreter,double&gt;(interpreter,&amp;Interpreter::sendDouble)]
			);
		}
		boost::spirit::rule&lt;ScannerT&gt; const&amp; start() const{
			return first;
		}
                //ende grammatik
	};
};
</code></pre>
<p>so, ein ziemlich wustes undurchdringliches stück code, verzeiht mir bitte die form des aufrufs der functoren, aber ich hatte da noch keine zeit eine passende funktion zu basteln, der code ist eigentlich nur sehr experimentell^^<br />
so wie der code da steht funktioniert er, das problem ist nur, dass ich keine möglichkeit habe über einen ctor einen interpreter/functoren einzumogeln. kennt jemand von euch noch eine halbwegs anständige möglichkeit?</p>
<p>ich will nicht auf einfache funktionen zurückgreifen müssen, da ich ehrlich gesagt keine ahnung hätte, wie ich das anstellen sollte.</p>
<p>ps: bitte interpretiert das als hilfeschrei, ich sitz an dem problem jetzt schon seit 3 tagen, und bin keinen milimeter weitergekommen.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/85108/dickes-designproblem</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 10:57:28 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/85108.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 05 Sep 2004 20:34:05 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to dickes designproblem on Sun, 05 Sep 2004 20:34:05 GMT]]></title><description><![CDATA[<p>ich arbeite ja mit boost::spirit, und ich wollte das konzept irgendwie mit klassen in einklang bringen, aber irgendwie scheitere ich ziemlich, darüber sind auchs chon ein paar tränen und jede menge schweiß geflossen(ergo ich hab darüber aufm hometrainer nachgedacht :D) das problem sind keine fehlermeldungen, sondern dass ich es nicht schaffe die instanz einer klasse an die &quot;informationen verarbeitende stellen&quot; zu bringen,dh klassen sind nicht gut mit spirit in einklang zu bringen, aber zuerst etwas unausgegorenen code:</p>
<pre><code class="language-cpp">//ich brauche hier die functoren, da spirit keine methoden annimmt.
template&lt;class Type&gt;
class sendChar{
	private:
		typedef void (Type::*function)(char);
		Type&amp; classPointer;
		function functionPointer;
		char sign;
	public:
		sendChar(Type&amp; instance,function pointer,char signToSend):classPointer(instance),functionPointer(pointer),sign(signToSend){}
		//der op ist so von spirit vorgegeben, deshalb dieser umweg über den ctor
                void operator()(char const*, char const*)const{
			(classPointer.*functionPointer)(sign);
		}

};
template&lt;class Type,class numberType&gt;
class SendNumber{
	private:
		typedef void (Type::*function)(numberType);
		Type&amp; classPointer;
		function functionPointer;
	public:
		SendNumber(Type&amp; instance,function pointer):classPointer(instance),functionPointer(pointer){}
                void operator()(numberType number)const{
			(classPointer.*functionPointer)(number);
		}
};
//hier ist meine &quot;verarbeitende klasse&quot;
class Interpreter{
public:
	void sendSign(char a){
		//hier werden die werte bearbeitet
	}
	void sendDouble(double value){
		//hier werden die doubles verarbeitet
	}
};

//die formd er klasse sit von spirit so vorgegeben, definition ist der einzige benutzte teil, ich hab deshalb keine chance von aussen irgendeine instanz reinzuschmuggeln
struct calculation:public boost::spirit::grammar&lt;calculation&gt;{
	template &lt;typename ScannerT&gt;
	struct definition{
		Interpreter interpreter;
		boost::spirit::subrule&lt;0&gt; real;

		boost::spirit::subrule&lt;1&gt; expression;
		boost::spirit::subrule&lt;2&gt; term;
		boost::spirit::subrule&lt;3&gt; group;
		boost::spirit::subrule&lt;4&gt; summand;

		boost::spirit::rule&lt;ScannerT&gt; first;
		definition(calculation const&amp; self){
                        //die grammatik ansich
			first=
			(
				expression=term|real,
				term=
					 summand
					 &gt;&gt;*(		('+'&gt;&gt;summand)[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'+')]
//hier wird der functor dann benutzt, wenn der parser bis zum op[] erfolgreich war, wird der functor aufgerufen
						|		('-'&gt;&gt;summand)[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'-')]
						),
				summand=
						(real|group)
						&gt;&gt;*(	('*'&gt;&gt;(real|group))[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'*')]
						|		('/'&gt;&gt;(real|group))[sendChar&lt;Interpreter&gt;(interpreter,&amp;Interpreter::sendSign,'/')]
						),
				group='('&gt;&gt;term&gt;&gt;')',

				real=boost::spirit::real_p[SendNumber&lt;Interpreter,double&gt;(interpreter,&amp;Interpreter::sendDouble)]
			);
		}
		boost::spirit::rule&lt;ScannerT&gt; const&amp; start() const{
			return first;
		}
                //ende grammatik
	};
};
</code></pre>
<p>so, ein ziemlich wustes undurchdringliches stück code, verzeiht mir bitte die form des aufrufs der functoren, aber ich hatte da noch keine zeit eine passende funktion zu basteln, der code ist eigentlich nur sehr experimentell^^<br />
so wie der code da steht funktioniert er, das problem ist nur, dass ich keine möglichkeit habe über einen ctor einen interpreter/functoren einzumogeln. kennt jemand von euch noch eine halbwegs anständige möglichkeit?</p>
<p>ich will nicht auf einfache funktionen zurückgreifen müssen, da ich ehrlich gesagt keine ahnung hätte, wie ich das anstellen sollte.</p>
<p>ps: bitte interpretiert das als hilfeschrei, ich sitz an dem problem jetzt schon seit 3 tagen, und bin keinen milimeter weitergekommen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/600288</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/600288</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 05 Sep 2004 20:34:05 GMT</pubDate></item><item><title><![CDATA[Reply to dickes designproblem on Mon, 06 Sep 2004 12:11:14 GMT]]></title><description><![CDATA[<blockquote>
<p>//die formd er klasse sit von spirit so vorgegeben, ..</p>
</blockquote>
<p>Das stimmt so nicht.<br />
<a href="http://boost.org/libs/spirit/doc/grammar.html" rel="nofollow">http://boost.org/libs/spirit/doc/grammar.html</a></p>
<p>Die Klasse calculator darf also schon<br />
Methoden, Variablen, etc.. haben.</p>
<p>Somit kannst die Funktoren ja an den Konstruktor von<br />
calculator übergeben. Ein kleines weiteres Problem<br />
wäre dann, dass du von definition ohne weiteres keinen<br />
Zugriff darauf hättest. Allerdings bekommst eh eine<br />
Referenz self auf die umhüllende Klasse.</p>
<p>Die ganzen Funktoren könntest aber auch ohne weiteres<br />
loswerden, wenn du boost::function und boost::bind<br />
benutzt.</p>
<p>Hier mal ein Lösungsansatz, musst halt noch auf dein<br />
Problem erweitern, kenn dafür boost::spirit nicht gut<br />
genug.</p>
<pre><code class="language-cpp">#include &lt;boost/spirit/utility/grammar_def.hpp&gt;
#include &lt;boost/spirit/core.hpp&gt;
#include &lt;boost/function.hpp&gt;
#include &lt;boost/bind.hpp&gt;
#include &lt;iostream&gt;

class Interpreter
{
	private:
		// ...	

	public:
		void pushChar(char)
		{ /* Hier den übergebenen Operator verarbeiten */ }

		void pushFloat(float)
		{ /* Hier die übergeben Zahl verarbeiten */	   }

		float getResult()
		{ /* Hier das Ergebniss zurückliefern */          }
};

template&lt;class InterpreterT&gt;
class Calculator : public boost::spirit::grammar&lt;Calculator&lt;InterpreterT&gt; &gt;
{
	private:
		InterpreterT&amp; interpreter_;
		boost::function&lt;void (char) &gt; pushChar;
		boost::function&lt;void (float)&gt; pushFloat;		

	public:
		Calculator(InterpreterT&amp; interpreter)
			: interpreter_(interpreter),
			  pushChar (boost::bind(&amp;InterpreterT::pushChar , interpreter_, _1)),
			  pushFloat(boost::bind(&amp;InterpreterT::pushFloat, interpreter_, _1))
		{	}

		template&lt;class ScannerT&gt;
		class definition
		{
			private:
				boost::function&lt;void (char) &gt; pushChar;
				boost::function&lt;void (float)&gt; pushFloat;

				boost::spirit::rule&lt;ScannerT&gt; op, term;

			public:
				definition(const Calculator&amp; self)
					: pushChar (self.pushChar ),
					  pushFloat(self.pushFloat)
				{
					using boost::spirit::ch_p;
					using boost::spirit::real_p;

					op   = ch_p('+')[pushChar] | ch_p('-')[pushChar];
					term = real_p[pushFloat] &gt;&gt; *(op &gt;&gt; real_p[pushFloat]);
				}

				const boost::spirit::rule&lt;ScannerT&gt;&amp; start() const
				{	return term; }
		};
};

bool parse_string(const char* str, Interpreter&amp; interpreter)
{
	static Calculator&lt;Interpreter&gt; calc(interpreter);

	return boost::spirit::parse(str, calc, boost::spirit::space_p).full;
}	

int main()
{
	std::string line;
	Interpreter interpreter;

	while(std::getline(std::cin, line)	
	   &amp;&amp; parse_string(line.c_str(), interpreter))
	{
		std::cout &lt;&lt; &quot;result: &quot; &lt;&lt; interpreter.getResult() &lt;&lt; std::endl;
	}
}
</code></pre>
<p>Hoffe, es hat geholfen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /><br />
Tankian</p>
]]></description><link>https://www.c-plusplus.net/forum/post/600585</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/600585</guid><dc:creator><![CDATA[Tankian]]></dc:creator><pubDate>Mon, 06 Sep 2004 12:11:14 GMT</pubDate></item><item><title><![CDATA[Reply to dickes designproblem on Mon, 06 Sep 2004 12:46:30 GMT]]></title><description><![CDATA[<blockquote>
<p>op = ch_p('+')[pushChar] | ch_p('-')[pushChar];</p>
</blockquote>
<p>hmm sicher ginge das so auch mit boost::function, aber ich könnte dann die automatische konvertierung von a+b in a b + vergessen, das war eigentlich der sinn des ganzen :), und durch die andere stellung ist nur der op()(char const*,char* const)const erlaubt, und boost::function unterstützt keine unterschiede zwischen dem typ der übergebenen funktion und op().</p>
<p>aber die sache mit dem ctor ist richtig, hab ich ganz übersehen, ich trottel^^<br />
ich war gestern späten abend schon fast soweit, mir über policies die instanz als singleton zu holen^^</p>
]]></description><link>https://www.c-plusplus.net/forum/post/600666</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/600666</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Mon, 06 Sep 2004 12:46:30 GMT</pubDate></item><item><title><![CDATA[Reply to dickes designproblem on Mon, 06 Sep 2004 13:44:46 GMT]]></title><description><![CDATA[<p>Aus deiner Antwort werd ich nicht gerade schlau :f</p>
<blockquote>
<p>automatische konvertierung von a+b in a b + vergessen</p>
</blockquote>
<p>Falls ich das jetzt richtig verstanden habe, meins das a b + eingegeben werden<br />
und richtig verarbeitet werden kann ?</p>
<p>a b + sollte sowieso nicht geschluckt werden (zumindestens bei der Grammatik<br />
aus meinem Beispiel) und wenn du das unbedingt in der Form a b + haben willst,<br />
kannst das ja auch noch bei späterer Verarbeitung machen.</p>
<blockquote>
<p>und durch die andere stellung ist nur der op()(char const*,char* const)const erlaubt</p>
</blockquote>
<p>Was für ein operator()(const char*, const char*) const ?</p>
<p>Falls du meinst, dass du mehr als nur einzelne Zeichen, Zahlen sendest, das<br />
geht doch genauso mit boost::function.</p>
<pre><code class="language-cpp">class Interpreter
{
    // ...
    public:
        void pushStrings(const char*, const char*)
        {        }

        // ...
};

template&lt;class InterpreterT&gt;
class Calculator : public boost::spirit::grammar&lt;Calculator&lt;InterpreterT&gt; &gt;
{
    private:
        // ...
        boost::function&lt;void (const char* const char*)&gt; pushStrings;

    public:
        Calculator(Interpreter&amp; interpreter)
            : // ...
              pushStrings(boost::bind(&amp;InterpreterT::pushStrings, interpreter_, _1, _2))
        {    }

        template&lt;class ScannerT&gt;
        class definition
        {
             private:
                  // ...
                  boost::function&lt;void (const char*, const char*)&gt; pushStrings;

                  boost::spirit::rule&lt;ScannerT&gt; op, term, expression;

             public:
                 definition(const Calculator&amp; self)
                     : // ...
                       pushStrings(self.pushStrings)
                 {  
                     op   = ch_p('+') | ch_p('-');
                     term = real_p &gt;&gt; *(op &gt;&gt; real_p);
                     expression = term[pushStrings];
                 }

                 const boost::spirit::rule&lt;ScannerT&gt;&amp; start() const
                 {   return expression; }
        };
};
</code></pre>
<p>Wobei ich das aber auch nicht gerade so gut finde, denn dann muss man sich<br />
selbst bei der Verarbeitung drum kümmern, den String zu zerlegen in dei<br />
einzelnen Ausdrücke. Darum würd ichs lieber gleich zerlegt senden.</p>
<p>Schätze mal ich hab dich aber doch wohl falsch verstanden <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /><br />
Tankian</p>
]]></description><link>https://www.c-plusplus.net/forum/post/600757</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/600757</guid><dc:creator><![CDATA[Tankian]]></dc:creator><pubDate>Mon, 06 Sep 2004 13:44:46 GMT</pubDate></item><item><title><![CDATA[Reply to dickes designproblem on Mon, 06 Sep 2004 15:26:27 GMT]]></title><description><![CDATA[<p>aus meiner antwort wird man auch nur schlau, wenn man sich etwas mit dem parsen von strings auseinandergesetzt hat(das drachenbuch gibt aufschluss)</p>
<p>der string a+b kann nicht gut interpretiert werden, deshalb wandelt der parser das für nachfolgende verarbeitungsschritte in a b + um. diese form nennt man Reverse Polish Notation (RPN).</p>
<blockquote>
<p>Was für ein operator()(const char*, const char*) const</p>
</blockquote>
<p>dies ist die normale form des op() bzw einer funktion, die boost::spirit im op[] schluckt, jediglich wenige einzelparser unterstützen andere funktionen(real_p void (double), ch_p void(char) usw).</p>
<p>eine gruppe von parsern bzw eine regel unterstützt standardmäßig nur funktionen der von mir genannten form.</p>
<blockquote>
<p>Wobei ich das aber auch nicht gerade so gut finde, denn dann muss man sich<br />
selbst bei der Verarbeitung drum kümmern, den String zu zerlegen in dei<br />
einzelnen Ausdrücke. Darum würd ichs lieber gleich zerlegt senden.</p>
</blockquote>
<p>du brauchst einzelne strings, wenn du zb ganze ausdrücke wie variablennamen parsen lassen willst.</p>
<p>operator()(const char*, const char*) wurde von boost::spirit als unterstützter standardoperator genommen, da man wesentlich öfter strings als zeichen bzw zeichen ausgeben muss. das man diese funktionen misbrauchen kann, um zb fehlermeldungen auszugeben,das ist sogar von spirit beabsichtigt:</p>
<p>zb</p>
<pre><code class="language-cpp">void error (const char*, const char*){
    cout&lt;&lt;&quot;string stellt keine zahl dar&quot;;
}
//im parser
real_p|eps_p[&amp;error]
</code></pre>
<p>eps_p stellt einen nullparser da(dh eps_p parst kein zeichen des strings und ruft nur error auf).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/600788</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/600788</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Mon, 06 Sep 2004 15:26:27 GMT</pubDate></item><item><title><![CDATA[Reply to dickes designproblem on Mon, 06 Sep 2004 19:29:48 GMT]]></title><description><![CDATA[<p>ok, das grundsätzliche problem der benutzbarmachung des parsers habe ich hinter mir, nun hatte ich ein bischen mehr zeit, mich um das desgin des mathe parsers zu beschäftigen, imho sieht mein ansatz so aus:</p>
<p>zuerst wirkt der parser ansich seines amtes, mithilfe der grammatik teilt er den string in stücke, und schickt die stücke an einen interpreter.<br />
der interpreter interpretiert die stringteile, und macht daraus einzelne pakete</p>
<p>zb wenn ein string '+' heisst, liefert der interpreter eine struktur, welche einen operator+ darstellt.</p>
<p>im letzten schritt holt sich dann eine klasse &quot;parseTree&quot; die pakete ab, und baut damit einen baum, der bei bedarf vom progrmam ausgeführt werden kann.</p>
<p>frage: ist das so praktikabel? ließe sich das prinzip auch hinterher noch erweitern(also zb auf typunterscheidung, variablen,if/else usw)? oder reicht das system grade mal für einfachste mathematische spielereien(also sowas wie 1+2*3+cos(4))</p>
]]></description><link>https://www.c-plusplus.net/forum/post/601079</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/601079</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Mon, 06 Sep 2004 19:29:48 GMT</pubDate></item></channel></rss>