<?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 parsing]]></title><description><![CDATA[<p>Hey ich versuche gerade ein ini like format mit boost spirit zu parsen. das klappt so weit auch ganz gut, die gramatik funktioniert aber ich kriege das automatische mapping in ein struct nicht hin, irgendwo fehlt mir da die richtige denkweise. Erstmal das format:</p>
<pre><code>[fine]
@cmp1
@cmp2
muh=b

[fail]
@cmp1
a=b
@cmp2
</code></pre>
<p>Das struct:</p>
<pre><code>typedef std::map&lt;std::string, std::string&gt; Pairs;
struct Section
{
	std::string name;
	std::vector&lt;std::string&gt; requirements;
	Pairs properties;
};
</code></pre>
<p>die &quot;fine&quot; variante lässt sich ziemlich gut beschreiben und die krieg ich auch richtig geparst und in das struct geschrieben (andere grammatik). Die fail variante wird (mit der gezeigten grammatik) richtig geparst aber ich krieg wie gesagt das automatische mapping nicht hin.</p>
<p>für das mapping hab ich:</p>
<pre><code>BOOST_FUSION_ADAPT_STRUCT(
	Section, 
	(std::string, name)
	(std::vector&lt;std::string&gt;, requirements)
	(Pairs, properties)
)
</code></pre>
<p>Ich weis das das händisch einfacher geht aber ich versuch mich gerade ein bischen an spirit und würde das gerne damit hin bekommen <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="🙂"
    /></p>
<p>gramatik:</p>
<pre><code>template &lt;typename Iterator, typename Skipper&gt;
struct SectionParser : qi::grammar&lt;Iterator, Section(), Skipper&gt;
{
	qi::rule&lt;Iterator, Section(), Skipper&gt; start;
	qi::rule&lt;Iterator, std::string()&gt; value, ident, name, component;
	qi::rule&lt;Iterator, std::pair&lt;std::string, std::string&gt;()&gt; pair;
		SectionParser() 
		: SectionParser::base_type(start, &quot;section grammar&quot;)
	{
		ident = +qi::char_(&quot;a-zA-Z0-9_&quot;);
		component = qi::char_('@') &gt; ident &gt;&gt; (qi::eol | qi::eoi);
		value = *(qi::char_ - (qi::eol | qi::eoi));
		pair = ident &gt; qi::lit('=') &gt; value &gt;&gt; (qi::eol | qi::eoi);
		name = qi::lit('[') &gt; ident &gt; qi::lit(']') &gt;&gt; (qi::eol | qi::eoi);
		start = name &gt;&gt; *(component | pair);
		BOOST_SPIRIT_DEBUG_NODES((start)(value)(pair)(component)(ident)(name));
	}
};
</code></pre>
<p>der skipper ist ein qi::blank.</p>
<p>am ende soll da halt ein std::vector&lt;Section&gt; rauskommen, hoffe ihr könnt mir helfen <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="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/332308/boost-spirit-parsing</link><generator>RSS for Node</generator><lastBuildDate>Tue, 28 Apr 2026 00:50:26 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/332308.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 21 Apr 2015 14:47:21 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to boost spirit parsing on Tue, 21 Apr 2015 14:49:25 GMT]]></title><description><![CDATA[<p>Hey ich versuche gerade ein ini like format mit boost spirit zu parsen. das klappt so weit auch ganz gut, die gramatik funktioniert aber ich kriege das automatische mapping in ein struct nicht hin, irgendwo fehlt mir da die richtige denkweise. Erstmal das format:</p>
<pre><code>[fine]
@cmp1
@cmp2
muh=b

[fail]
@cmp1
a=b
@cmp2
</code></pre>
<p>Das struct:</p>
<pre><code>typedef std::map&lt;std::string, std::string&gt; Pairs;
struct Section
{
	std::string name;
	std::vector&lt;std::string&gt; requirements;
	Pairs properties;
};
</code></pre>
<p>die &quot;fine&quot; variante lässt sich ziemlich gut beschreiben und die krieg ich auch richtig geparst und in das struct geschrieben (andere grammatik). Die fail variante wird (mit der gezeigten grammatik) richtig geparst aber ich krieg wie gesagt das automatische mapping nicht hin.</p>
<p>für das mapping hab ich:</p>
<pre><code>BOOST_FUSION_ADAPT_STRUCT(
	Section, 
	(std::string, name)
	(std::vector&lt;std::string&gt;, requirements)
	(Pairs, properties)
)
</code></pre>
<p>Ich weis das das händisch einfacher geht aber ich versuch mich gerade ein bischen an spirit und würde das gerne damit hin bekommen <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="🙂"
    /></p>
<p>gramatik:</p>
<pre><code>template &lt;typename Iterator, typename Skipper&gt;
struct SectionParser : qi::grammar&lt;Iterator, Section(), Skipper&gt;
{
	qi::rule&lt;Iterator, Section(), Skipper&gt; start;
	qi::rule&lt;Iterator, std::string()&gt; value, ident, name, component;
	qi::rule&lt;Iterator, std::pair&lt;std::string, std::string&gt;()&gt; pair;
		SectionParser() 
		: SectionParser::base_type(start, &quot;section grammar&quot;)
	{
		ident = +qi::char_(&quot;a-zA-Z0-9_&quot;);
		component = qi::char_('@') &gt; ident &gt;&gt; (qi::eol | qi::eoi);
		value = *(qi::char_ - (qi::eol | qi::eoi));
		pair = ident &gt; qi::lit('=') &gt; value &gt;&gt; (qi::eol | qi::eoi);
		name = qi::lit('[') &gt; ident &gt; qi::lit(']') &gt;&gt; (qi::eol | qi::eoi);
		start = name &gt;&gt; *(component | pair);
		BOOST_SPIRIT_DEBUG_NODES((start)(value)(pair)(component)(ident)(name));
	}
};
</code></pre>
<p>der skipper ist ein qi::blank.</p>
<p>am ende soll da halt ein std::vector&lt;Section&gt; rauskommen, hoffe ihr könnt mir helfen <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="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2451079</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451079</guid><dc:creator><![CDATA[foofel]]></dc:creator><pubDate>Tue, 21 Apr 2015 14:49:25 GMT</pubDate></item><item><title><![CDATA[Reply to boost spirit parsing on Wed, 22 Apr 2015 10:24:22 GMT]]></title><description><![CDATA[<p>ok habs <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="🙂"
    /></p>
<p>kein adapt struct mehr. das struct ist das selbe. die grmattik ist:</p>
<pre><code>template &lt;typename Iterator, typename Skipper&gt;
	struct SectionParser : qi::grammar&lt;Iterator, Section(), Skipper&gt;
	{
		qi::rule&lt;Iterator, Section(), Skipper&gt; start;
		qi::rule&lt;Iterator, std::string()&gt; value, ident, name, component;
		qi::rule&lt;Iterator, std::pair&lt;std::string, std::string&gt;()&gt; pair;

		SectionParser() 
			: SectionParser::base_type(start, &quot;section grammar&quot;)
		{
			auto add_component = phx::push_back(phx::bind(&amp;Section::requirements, qi::_val), qi::_1);
			auto add_pair = phx::insert(phx::bind(&amp;Section::properties, qi::_val), qi::_1);
			auto set_name = phx::assign(phx::bind(&amp;Section::name, qi::_val), qi::_1);

			ident = +qi::char_(&quot;a-zA-Z0-9_&quot;);
			component = qi::char_('@') &gt; ident &gt;&gt; (qi::eol | qi::eoi);
			value = *(qi::char_ - (qi::eol | qi::eoi));
			pair = ident &gt; qi::lit('=') &gt; value &gt;&gt; (qi::eol | qi::eoi);
			name = qi::lit('[') &gt; ident &gt; qi::lit(']') &gt;&gt; (qi::eol | qi::eoi);
			start = name[set_name] &gt;&gt; *(component[add_component] | pair[add_pair]);

			BOOST_SPIRIT_DEBUG_NODES((value)(pair)(component)(ident)(name));
		}
	};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2451186</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451186</guid><dc:creator><![CDATA[foofel]]></dc:creator><pubDate>Wed, 22 Apr 2015 10:24:22 GMT</pubDate></item><item><title><![CDATA[Reply to boost spirit parsing on Wed, 22 Apr 2015 11:05:10 GMT]]></title><description><![CDATA[<p>Das kann man sicherlich locker ohne Spirit parsen. Können wir auch eine solche Lösung vorschlagen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2451187</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451187</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Wed, 22 Apr 2015 11:05:10 GMT</pubDate></item><item><title><![CDATA[Reply to boost spirit parsing on Wed, 22 Apr 2015 15:25:34 GMT]]></title><description><![CDATA[<p>Wenn du was schönes hast sicher <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="🙂"
    /> zusammengefasst müßte man in etwa sowas parsen:</p>
<pre><code>; comment one
/* comment two */

[entity]
@component
property=one
; comment 

property = two or more
@component2
[@component]
property=three
/*four=five

six=seven*/

[@component2]

[entity2:entity]
property=something else
prop2 =new ; skip me

[entity3]
</code></pre>
<p>hoffe ich hab so mehr oder weniger die meisten fälle abgedeckt. Wie gesagt, das da abhängigkeiten drinne sind ist fürs parsen erstmal egal, hauptsache die sections kommen sauber raus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2451197</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451197</guid><dc:creator><![CDATA[foofel]]></dc:creator><pubDate>Wed, 22 Apr 2015 15:25:34 GMT</pubDate></item><item><title><![CDATA[Reply to boost spirit parsing on Mon, 27 Apr 2015 10:25:32 GMT]]></title><description><![CDATA[<p>Ich dachte an etwas in der Richtung:</p>
<pre><code>#include &lt;algorithm&gt;
#include &lt;iostream&gt;

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

#include &lt;cstring&gt;

struct Char { char ch; };

std::istream&amp; operator&gt;&gt;(std::istream&amp; is, Char ch) {
	char c;
	if (is &gt;&gt; c &amp;&amp; ch.ch != c)
		is.setstate(std::ios::failbit);
	return is;
}

std::string rtrim(std::string const&amp; s) {
	return {begin(s), std::find_if(s.rbegin(), s.rend(), [] (char c) {return !std::isspace(c);}).base()};
}

struct CommentCharTraits {
	std::string startOL, openML, closeML;
};

struct SectionCharTraits {
	char openNameBracket;
	char closedNameBracket;
	char reqIntroducer;
	char keyValueSeparator;
};

std::string stripComments(char const* str,
                          CommentCharTraits traits = {&quot;;&quot;, &quot;/*&quot;, &quot;*/&quot;})
{
	const std::size_t len  = std::strlen(str);
	std::string res; res.reserve(len);
	for (auto end = str+len; str != end; ++str)
		if (traits.startOL.compare(0, std::string::npos, str, traits.startOL.size()) == 0)
			str = std::find(str, end, '\n');
		else if (traits.openML.compare(0, std::string::npos, str, traits.openML.size()) == 0) {
			if (!(str = std::strstr(str+1, traits.closeML.c_str())))
				return res;
			str += traits.closeML.size();
		}
		else res.push_back(*str);

	return res;
}

typedef std::map&lt;std::string, std::string&gt; Pairs;
struct Section
{
	std::string name;
	std::vector&lt;std::string&gt; requirements;
	Pairs properties;
};

void read( std::istream&amp; is, Section&amp; s, SectionCharTraits traits )
{
	is &gt;&gt; Char{traits.openNameBracket};
	std::getline(is, s.name, traits.closedNameBracket);

	for (; is &gt;&gt; std::ws;) {
		std::string tmp;
		char peek = is.peek();
		if (peek == traits.reqIntroducer) {
			if (!std::getline(is.ignore(), tmp))
				break;
			s.requirements.push_back(std::move(tmp));
		}
		else if (peek == traits.openNameBracket)
			break;
		else {
			std::string tmp2;
			if (!std::getline(is, tmp, traits.keyValueSeparator)
			 || !std::getline(is, tmp2))
				break;
			s.properties[rtrim(tmp)] = rtrim(tmp2);
		}
	}
}
</code></pre>
<p>Nicht ausführlich getestet, wird wahrscheinlich ein paar Macken haben, vor allem wenn es um Fehlererkennung geht.<br />
Könnte dann so verwendet werden:</p>
<pre><code>#include &lt;sstream&gt;

int main() {
	std::istringstream stream(stripComments(
		R&quot;( ; comment one
		/* comment two */

		[entity]
		@component
		property=one
		; comment

		property = two or more
		@component2
		[@component]
		property=three
		/*four=five

		six=seven*/

		[@component2]

		[entity2:entity]
		property=something else
		prop2 =new ; skip me

		[entity3])&quot;));

	Section s;
	read(stream, s, {'[', ']', '@', '='});

	std::cout &lt;&lt; s.name &lt;&lt; '\n';
	for (auto&amp;&amp; r : s.requirements)
		std::cout &lt;&lt; r &lt;&lt; '\n';
	for (auto&amp;&amp; p : s.properties)
		std::cout &lt;&lt; p.first &lt;&lt; &quot; = &quot; &lt;&lt; p.second &lt;&lt; '\n';
}
</code></pre>
<p>Ich würde jedoch bei Spirit bleiben, der Code ist komplizierter geworden als gedacht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2451665</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451665</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 27 Apr 2015 10:25:32 GMT</pubDate></item><item><title><![CDATA[Reply to boost spirit parsing on Mon, 27 Apr 2015 12:30:56 GMT]]></title><description><![CDATA[<p>Kannes vom mobilen Geraet nicht testen, aber /*/ duerfte faelschlicherweise als Kommentar erkannt werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2451676</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451676</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 27 Apr 2015 12:30:56 GMT</pubDate></item><item><title><![CDATA[Reply to boost spirit parsing on Mon, 27 Apr 2015 14:21:13 GMT]]></title><description><![CDATA[<p>Hab auch noch mal ein bischen weiter gebastelt, aktuell: <a href="https://ideone.com/LllC26" rel="nofollow">https://ideone.com/LllC26</a></p>
<p>Ich hab mal versucht das ganze über die automatische generierung laufen zu lassen. Das funktioniert wie gesagt ziemlich gut wenn sich die &quot;@comp&quot; und &quot;prop=val&quot; lines nicht vermischen aber ich hab noch immer keine ahnung wie ich das anstell wenn die nicht blockweise geordnen in der datei stehen...</p>
<p>Muss doch noch spirit profis hier geben <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2451688</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2451688</guid><dc:creator><![CDATA[foofel]]></dc:creator><pubDate>Mon, 27 Apr 2015 14:21:13 GMT</pubDate></item></channel></rss>