<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	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/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>johannes-asal.de</title>
	<atom:link href="http://www.johannes-asal.de/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.johannes-asal.de</link>
	<description></description>
	<lastBuildDate>Tue, 03 Aug 2010 07:04:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>MR.bee live beim Kieswerk Open Air</title>
		<link>http://www.johannes-asal.de/?p=215</link>
		<comments>http://www.johannes-asal.de/?p=215#comments</comments>
		<pubDate>Tue, 03 Aug 2010 06:59:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Musik]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=215</guid>
		<description><![CDATA[Am Mittwoch den 04.08. live beim Kieswerk Open Air ab ca. 19 Uhr mit Coverversionen von Katie Melua, Billy Joel, Jack Johnson, The Eagles, Robbie Williams und andern. Im Anschluss Filmvorfuehrung auf Grossleinwand &#8220;Mit dir an meiner Seite&#8221;. Weitere Infos unter http://www.kieswerk-open-air.de/ und http://mrbee.johannes-asal.de/.]]></description>
			<content:encoded><![CDATA[<p>Am Mittwoch den 04.08. live beim Kieswerk Open Air ab ca. 19 Uhr mit Coverversionen von Katie Melua, Billy Joel, Jack Johnson, The Eagles, Robbie Williams und andern. Im Anschluss Filmvorfuehrung auf Grossleinwand &#8220;Mit dir an meiner Seite&#8221;. Weitere Infos unter <a href="http://www.kieswerk-open-air.de/">http://www.kieswerk-open-air.de/</a> und <a href="http://mrbee.johannes-asal.de/">http://mrbee.johannes-asal.de/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=215</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers in Python mit PLY (Teil 1)</title>
		<link>http://www.johannes-asal.de/?p=199</link>
		<comments>http://www.johannes-asal.de/?p=199#comments</comments>
		<pubDate>Thu, 17 Jun 2010 14:26:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=199</guid>
		<description><![CDATA[Nach der Entwicklung eines Parsers fuer Konfigurationsdateien in C++ kam mir der Gedanke, auch fuer andere Programmiersprachen entsprechende Parser zu schreiben, um die gemeinsame Nutzung ein und derselben Konfigurationen in mehreren Sprachen zu ermoeglichen. Dies ist insbesondere in der Entwicklung von Applikationen von Interesse, die ein prozessbasiertes mehrschichtiges Design aufweisen und jeweils die am besten [...]]]></description>
			<content:encoded><![CDATA[<p>Nach der Entwicklung eines Parsers fuer Konfigurationsdateien in C++ kam mir der Gedanke, auch fuer andere Programmiersprachen entsprechende Parser zu schreiben, um die gemeinsame Nutzung ein und derselben Konfigurationen in mehreren Sprachen zu ermoeglichen. Dies ist insbesondere in der Entwicklung von Applikationen von Interesse, die ein prozessbasiertes mehrschichtiges Design aufweisen und jeweils die am besten geeignete Programmiersprache fuer jede Schicht verwenden. Hat man in solchen Faellen kein gemeinsames Konfigurationsmodell zur Verfuegung, so muessen saemtliche relevanten Daten von der Controller Applikation an die anderen Prozesse weitergegeben werden, was aber wiederum die Verwendung eines speziellen Protokolls voraussetzt, um die Daten zwischen den Prozessen auszutauschen. Fuer solche Anwendungen ist es sicherlich einfacher, die Konfiguration zentral zu verwalten und in jedem Prozess separat einzulesen.</p>
<p>Die erste Programmiersprache, die ich in diesem Zusammenhang angegangen habe, ist Python. Fuer Python existiert mit PLY ein einfacher aber dennoch leistungsfaehiger Parser Generator, der gegenueber dem C++-Pendant boost::spirit auf die Vorteile einer dynamischen Sprache zurueckgreifen kann. Bereits nach 15 Minuten hatte ich einen funktionsfaehigen Lexer implementiert, der mir einen Tokenstream fuer das Konfigurationsformat lieferte. Nach weiteren 20 Minuten war auch der Parser fertiggestellt. Das zeigt, dass PLY viel besser als boost::spirit fuer Rapid Prototyping geeignet ist, zumal auch das Testen von Lexer und Parser dank schneller Instanziierung im Python Interpreter zuegig von der Hand geht.</p>
<p>In diesem Artikel moechte ich kurz anreissen, wie sich ein Parser fuer unser Konfigurationsformat (siehe vorangegangene Artikel) mit PLY implementieren laesst. Details sollen diesmal aussen vor bleiben, dazu verweise ich auf den Sourcecode, der am Ende des zweiten Teils verlinkt ist. Fuer ein erstes Experimentieren mit PLY sollten die Ausfuehrungen jedoch ausreichend sein, zumal Python mit seinem Interpreter eine ideale Testumgebung bietet.</p>
<p>Um den zu parsenden String in einzelne Tokens zu zerlegen, benoetigen wir einen Lexer. Dieser muss sowohl Keywords (in unserem Fall sind das &#8216;true&#8217; und &#8216;false&#8217;), einzelne Zeichen (Klammern, Semikolon, Komma und &#8216;=&#8217;) sowie die atomaren Datentypen (double, long und string) erkennen koennen. Im Gegensatz zu boost::spirit koennen wir in PLY direkt regulaere Ausdruecke verwenden, um die einzelnen Token zu spezifizieren. Diese fassen wir geeigneterweise in einer Klasse zusammen (auch alle folgenden Codesegmente sollen als Member dieser Klasse angelegt werden). Zunaechst definieren wir eine Liste &#8216;tokens&#8217; (der Name ist vorgegeben), die die (frei waehlbaren) Namen der Tokens enthaelt.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> CfgLexer<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
  keywords = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'TRUE'</span>, <span style="color: #483d8b;">'FALSE'</span><span style="color: black;">&#41;</span>
  tokens = keywords + <span style="color: black;">&#40;</span>
    <span style="color: #483d8b;">'LPAREN'</span>, <span style="color: #483d8b;">'RPAREN'</span>,
    <span style="color: #483d8b;">'LBRACKET'</span>, <span style="color: #483d8b;">'RBRACKET'</span>,
    <span style="color: #483d8b;">'LBRACE'</span>, <span style="color: #483d8b;">'RBRACE'</span>,
    <span style="color: #483d8b;">'COMMA'</span>,
    <span style="color: #483d8b;">'EQUALS'</span>,
    <span style="color: #483d8b;">'SEMICOLON'</span>,
    <span style="color: #483d8b;">'LITERAL'</span>,
    <span style="color: #483d8b;">'DOUBLE'</span>,
    <span style="color: #483d8b;">'LONG'</span>,
    <span style="color: #483d8b;">'STRING_LITERAL'</span>
  <span style="color: black;">&#41;</span></pre></div></div>

<p>Fuer die beiden Keywords &#8216;TRUE&#8217; und &#8216;FALSE&#8217; habe ich zudem eine separate Liste angelegt; der Grund dafuer ist, dass fuer die Keywords beim Parsen nicht zwischen Gross- und Kleinschreibung unterschieden werden soll und diese deshalb spaeter gesondert behandelt werden muessen.</p>
<p>Um die Tokens festzulegen, fuegen wir der Klasse nun regulaere Ausdruecke fuer jedes der Tokens hinzu und weisen diese jeweils einer Variablen &#8216;t_TOKENNAME&#8217; hinzu, also folgendermassen:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t_LPAREN = <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\(</span>&quot;</span>
t_RPAREN = <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\)</span>&quot;</span>
t_LBRACKET = <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\[</span>&quot;</span>
t_RBRACKET = <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\]</span>&quot;</span>
t_LBRACE = <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\{</span>&quot;</span>
t_RBRACE = <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\}</span>&quot;</span>
t_COMMA = <span style="color: #483d8b;">&quot;,&quot;</span>
t_EQUALS = <span style="color: #483d8b;">&quot;=&quot;</span>
t_SEMICOLON = <span style="color: #483d8b;">&quot;;&quot;</span></pre></div></div>

<p>Beachten Sie, dass die Klammern escaped werden muessen, da es sich bei den Strings um regulaere Ausdruecke handelt, und die Klammern sonst als Steuerzeichen interpretiert werden.</p>
<p>Fuer die uebrigen Tokens reicht ein einfaches Matching nicht aus, wir muessen ausserdem Aktionen verknuepfen, die bei einem erfolgreichen Match ausgefuehrt werden. Dazu koennen wir wie zuvor eine Variable mit einem regulaeren Ausdruck definieren und diese anschliessend an eine Funktion binden:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">literal = <span style="color: #483d8b;">&quot;[a-zA-Z_][0-9a-zA-Z]*&quot;</span>
&nbsp;
@TOKEN<span style="color: black;">&#40;</span>literal<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> t_LITERAL<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, t<span style="color: black;">&#41;</span>:
  t.<span style="color: #008000;">type</span> = <span style="color: #008000;">self</span>.<span style="color: black;">keyword_map</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>t.<span style="color: black;">value</span>.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">&quot;LITERAL&quot;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> t</pre></div></div>

<p>Nach einem erfolgreichen Match des regulaeren Ausdrucks suchen wir also zuerst in einer Keyword Map, ob wir ein passendes Keyword finden (beachten Sie die lowercase Transformation!) und verwenden dieses fuer den Typ des Tokens, ansonsten weisen wir den Typ &#8216;LITERAL&#8217; zu. Die Keyword Map definieren wir wie folgt:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">keyword_map = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> k <span style="color: #ff7700;font-weight:bold;">in</span> keywords:
  keyword_map<span style="color: black;">&#91;</span>k.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> = k</pre></div></div>

<p>Auch fuer die uebrigen Tokens muessen wir Funktionen definieren:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">string_literal = r<span style="color: #483d8b;">'&quot;[^&quot;<span style="color: #000099; font-weight: bold;">\n</span>]*&quot;'</span> + <span style="color: #483d8b;">'|'</span> + r<span style="color: #483d8b;">&quot;'[^'<span style="color: #000099; font-weight: bold;">\n</span>]*'&quot;</span>
double_constant = r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\-</span>?([1-9]<span style="color: #000099; font-weight: bold;">\d</span>* | 0)<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>*&quot;</span>
long_constant = r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\-</span>?[1-9]<span style="color: #000099; font-weight: bold;">\d</span>* | 0&quot;</span>
&nbsp;
@TOKEN<span style="color: black;">&#40;</span>string_literal<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> t_STRING_LITERAL<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, t<span style="color: black;">&#41;</span>:
  t.<span style="color: #008000;">type</span> = <span style="color: #483d8b;">&quot;STRING_LITERAL&quot;</span>
  t.<span style="color: black;">value</span> = t.<span style="color: black;">value</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span>'&quot;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> t
&nbsp;
@TOKEN<span style="color: black;">&#40;</span>double_constant<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> t_DOUBLE<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, t<span style="color: black;">&#41;</span>:
  t.<span style="color: #008000;">type</span> = <span style="color: #483d8b;">&quot;DOUBLE&quot;</span>
  t.<span style="color: black;">value</span> = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>t.<span style="color: black;">value</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> t
&nbsp;
@TOKEN<span style="color: black;">&#40;</span>long_constant<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> t_LONG<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, t<span style="color: black;">&#41;</span>:
  t.<span style="color: #008000;">type</span> = <span style="color: #483d8b;">&quot;LONG&quot;</span>
  t.<span style="color: black;">value</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>t.<span style="color: black;">value</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Bei den String Literals entfernen wir die Anfuehrungszeichen am Anfang und Ende, waehrend wir die value Felder der &#8216;DOUBLE&#8217; und &#8216;LONG&#8217; Tokens in den jeweiligen Datentyp konvertieren. Es fehlt nun nur noch ein Skip Parser, der den insignifikanten Whitespace ueberspringt (d.h. kein Token dafuer anlegt). Dazu weisen wir einen String mit zu ignorierenden Zeichen der (reservierten) Variablen t_ignore zu:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t_ignore = <span style="color: #483d8b;">&quot; <span style="color: #000099; font-weight: bold;">\t</span>&quot;</span></pre></div></div>

<p>Wir ueberspringen damit sowohl Leerzeichen als auch Tabs. Was geschieht aber mit den Linefeeds? Diese beduerfen wieder einer Sonderbehandlung:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> t_newline<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, t<span style="color: black;">&#41;</span>:
  r<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>+'</span>
  t.<span style="color: black;">lexer</span>.<span style="color: black;">lineno</span> += <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>t.<span style="color: black;">value</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Hier missbrauchen wir den Docstring, um den regulaeren Ausdruck unterzubringen (der Lexer interpretiert diesen automatisch als die zu verwendende Regular Expression) und addieren anschliessend die Anzahl der gematchten Linefeeds zur Variablen t.lexer.lineno, um in den Fehlermeldungen auch die richtige Zeilennummer des fehlerhaften Tokens ausgeben zu koennen.</p>
<p>Wie wird nun ein solches Lexer Objekt erzeugt und auf die gelexten Tokens zugegriffen? Dazu definieren wir noch drei weitere Funktionen:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> build<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
  <span style="color: #008000;">self</span>.<span style="color: black;">lexer</span> = ply.<span style="color: black;">lex</span>.<span style="color: black;">lex</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span>=<span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">input</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, text<span style="color: black;">&#41;</span>:
  <span style="color: #008000;">self</span>.<span style="color: black;">lexer</span>.<span style="color: #008000;">input</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">token</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
  t = <span style="color: #008000;">self</span>.<span style="color: black;">lexer</span>.<span style="color: #dc143c;">token</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> t</pre></div></div>

<p>Nachdem wir noch die Import Statements &#8220;import ply.lex&#8221; und &#8220;from ply.lex import TOKEN&#8221; hinzugefuegt haben, koennen wir den Lexer bereits testen. Wir starten eine Python Konsole und importieren das Modul (das wir beispielsweise als cfg_lexer.py) gespeichert haben:<br />
<code><br />
>>> import cfg_lexer<br />
>>> lexer = cfg_lexer.CfgLexer()<br />
>>> lexer.build()<br />
>>> lexer.input("a=5; b=(1,2,"Hallo"); c = { test = "test"; hallo = "welt"; };")<br />
>>> lexer.token()<br />
LexToken(LITERAL,'a',1,0)<br />
>>> lexer.token()<br />
LexToken(EQUALS,'=',1,1)<br />
>>> lexer.token()<br />
LexToken(LONG,5,1,2)<br />
[...]<br />
</code></p>
<p>Wie funktioniert das ganze nun ueberhaupt? Eine solch lose Zusammenstellung von Funktionen in einer Klasse kann doch unmoeglich einen funktionsfaehigen Lexer darstellen! Der Trick ist, dass PLY die Liste der Tokens benutzt, um dynamisch die passenden Variablen bzw. Funktionen mit den regulaeren Ausdruecken in der Klasse zu suchen. Daraus wird on-the-fly Python Code fuer das Lexing generiert. Damit wird auch klar, warum die Benennung der Member unserer CfgLexer Klasse wichtig ist. Werden sie falsch bezeichnet, so findet PLY waehrend dem build() Prozess die regulaeren Ausdruecke bzw. semantischen Aktionen nicht und kann den Lexer nicht erstellen. Die Fehlermeldungen sind aber in diesem Fall deutlich besser verstaendlich als die C++ Templateerrors, die einen bei der Parserentwicklung mit boost::spirit erwarten.</p>
<p>Im naechsten Teil werden wir unseren Lexer als Tokenfeed benutzen und darauf aufbauend einen Parser implementieren.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=199</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers mit Hilfe von boost::spirit (Teil 4)</title>
		<link>http://www.johannes-asal.de/?p=179</link>
		<comments>http://www.johannes-asal.de/?p=179#comments</comments>
		<pubDate>Thu, 29 Apr 2010 16:11:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=179</guid>
		<description><![CDATA[In den bisherigen drei Teilen dieser Serie haben wir ein Format fuer Konfigurationsdateien erarbeitet, eine Spirit-Grammatik dafuer geschrieben und zuletzt eine Objekthierarchie fuer die Speicherung der Daten implementiert. Der wichtigste Teil fehlt jedoch noch: Die Erzeugung des Objektbaums waehrend des Parsens. Wir werden zu diesem Zweck direkt semantische Aktionen mit den einzelnen Regeln der Grammatik [...]]]></description>
			<content:encoded><![CDATA[<p>In den bisherigen drei Teilen dieser Serie haben wir ein Format fuer Konfigurationsdateien erarbeitet, eine Spirit-Grammatik dafuer geschrieben und zuletzt eine Objekthierarchie fuer die Speicherung der Daten implementiert. Der wichtigste Teil fehlt jedoch noch: Die Erzeugung des Objektbaums waehrend des Parsens. Wir werden zu diesem Zweck direkt semantische Aktionen mit den einzelnen Regeln der Grammatik assoziieren.</p>
<p>Warum benutzen wir nicht einfach den von Spirit automatisch generierten Baum? Wir koennten den Parser bereits im jetzigen Zustand (siehe Ende des Teils 2b) benutzen und den von Spirit generierten Objektbaum im aeusseren Attribut verwenden, um nachtraeglich den von uns gewuenschten Baum aus element Objekten aufzubauen. Betrachten wir jedoch einmal beispielsweise den Typ des automatisch generierten Attributs der Regel array, die wie folgt definiert war:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">arrayDefinition
  <span style="color: #000080;">=</span>  lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'['</span><span style="color: #008000;">&#41;</span>
  <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">-</span><span style="color: #008000;">&#40;</span> double_ <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #000040;">|</span> long_ <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #000040;">|</span> bool_ <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #000040;">|</span> string <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #008000;">&#41;</span>
  <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">']'</span>
  <span style="color: #008080;">;</span></pre></div></div>

<p>Diese Regel generiert ein Attribut vom Typ</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">optional<span style="color: #000080;">&lt;</span>
  variant<span style="color: #000080;">&lt;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span>,
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">long</span><span style="color: #000080;">&gt;</span>,
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">bool</span><span style="color: #000080;">&gt;</span>,
    vector<span style="color: #000080;">&lt;</span>string<span style="color: #000080;">&gt;</span>
  <span style="color: #000080;">&gt;</span>
<span style="color: #000080;">&gt;</span></pre></div></div>

<p>Die array Regel wird in listDefinition und variableAssignment verwendet, die ebenfalls ein variant generieren, welches wiederum das oben gezeigte variant der arrayDefinition in seiner Typenliste enthaelt usw. Wir wuerden fuer die aeussere Regel also ein Attribut erhalten, dessen Typdefinition so lang und verschachtelt ist, dass niemand ernsthaft darueber nachdenken wuerde, damit ueberhaupt eine Auswertung zu versuchen. Wir muessen also eine Loesung finden, uns von der statischen Typisierung zu loesen. Unsere element Klassenhierarchie ist dazu bestens geeignet und soll daher anstelle des automatisch generierten Baums verwendet werden.</p>
<p>Spirit ist eine DSEL (Domain Specific Embedded Language), die auf dem Sprachraum von C++ definiert ist. Dies bringt einige Nachteile mit sich, die insbesondere bei der Implementierung der semantischen Aktionen zum Tragen kommen. Da die Grammatik mitsamt der assoziierten semantischen Aktionen vom Compiler in ein Objekt uebersetzt wird, koennen wir fuer diese nicht einfach gewoehnlichen C++ Code benutzen, sondern muessen diesen wiederum in Objekte (Funktoren) kapseln, die dann zur Laufzeit ausgewertet werden koennen. Gluecklicherweise bietet boost::phoenix bereits eine Reihe von Funktoren an, die die meisten grundlegenden Operationen abdeckt (new, delete, Konstruktorenaufrufe, &#8230;).</p>
<p>Beginnen wir mit der atom Regel. Wir fuegen dieser eine semantische Aktion hinzu, die mit dem gesamten Ausdruck assoziiert sein soll (dazu klammern wir die Unterregeln einfach ein):</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">atom
  <span style="color: #000080;">=</span>  <span style="color: #008000;">&#40;</span> double_
     <span style="color: #000040;">|</span> long_
     <span style="color: #000040;">|</span> bool_
     <span style="color: #000040;">|</span> string
     <span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#91;</span> _val <span style="color: #000080;">=</span> new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">atom</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>_1<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#93;</span>
  <span style="color: #008080;">;</span></pre></div></div>

<p>Semantische Aktionen werden in eckige Klammern eingeschlossen und der Teilregel angehaengt, fuer die das Attribut verarbeitet werden soll. Der Typ des generierten Attributs fuer den gesamten Ausdruck</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #008000;">&#40;</span> double_ <span style="color: #000040;">|</span> long_ <span style="color: #000040;">|</span> bool_ <span style="color: #000040;">|</span> string <span style="color: #008000;">&#41;</span></pre></div></div>

<p> ist</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">variant<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, <span style="color: #0000ff;">long</span>, <span style="color: #0000ff;">bool</span>, string<span style="color: #000080;">&gt;</span></pre></div></div>

<p> Wir erinnern uns, dass wir in unserer Atom Klasse einen Konstruktor mit genau diesem Typ als Parameter definiert hatten. Normalerweise koennten wir dann ein Objekt vom Typ atom erzeugen, indem wir</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000dd;">new</span> atom<span style="color: #008000;">&#40;</span>generated_attribute<span style="color: #008000;">&#41;</span></pre></div></div>

<p> schreiben. Fuer Spirit muessen wir dies allerdings in einen phoenix Ausdruck uebersetzen (new_ ist der phoenix Funktor fuer new).</p>
<p>Auf das generierte Attribut koennen wir ueber den Platzhalter _1 zugreifen. Den Zeiger auf das neu erzeugte atom Objekt weisen wir dem Platzhalter _val zu, der diesen als das generierte Attribut der gesamten Regel festlegt. Fassen wir noch einmal zusammen: Ohne die semantische Aktion wuerde die atom Regel ein Attribut vom Typ variant zurueckliefern, jedoch moechten wir stattdessen ein atom Objekt aus unserer Objekthierarchie zurueckgeben, und setzen dieses mittels Zuweisung an _val als das neue generierte Attribut.</p>
<p>Um das Attribut der Regel string (und literal) muessen wir uns nicht kuemmern, da Spirit automatisch ein std::string Attribut erzeugt, wenn wir std::string als Rueckgabewert der Regel festlegen (die Typen sind kompatibel, d.h. es existiert bereits eine Transformationsvorschrift, die das Attribut der Regel in einen String umwandeln kann &#8211; dies ist fuer benutzerdefinierte Typen natuerlich leider nie der Fall).</p>
<p>Betrachten wir als naechstes die listDefinition. Fuer diese muessen wir mehrere Aktionen verwenden. Zu Beginn der Regel muss ein neues Objekt vom Typ list (aus unserer Objekthierarchie) angelegt werden, das wir in _val zwischenspeichern. Fuer jede nun folgende groupDefinition, listDefinition, arrayDefinition oder atom muss das zugehoerige Attribut an das list Objekt angehaengt werden. Wir erinnern uns, dass wir dem list Objekt eine Funktion append(element*) gegeben hatten. Diese Funktion koennen wir allerdings in der semantischen Aktion nicht ohne weiteres verwenden, sondern muessen sie zunaechst in einen Struct kapseln:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">struct</span> append_impl
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> C, <span style="color: #0000ff;">typename</span> Arg<span style="color: #000080;">&gt;</span>
  <span style="color: #0000ff;">struct</span> result <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">void</span> type<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> C, <span style="color: #0000ff;">typename</span> Arg<span style="color: #000080;">&gt;</span>
  <span style="color: #0000ff;">void</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span>C<span style="color: #000040;">*</span> c, <span style="color: #0000ff;">const</span> Arg<span style="color: #000040;">&amp;</span> data<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
  <span style="color: #008000;">&#123;</span> c<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>append<span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
phoenix<span style="color: #008080;">::</span><span style="color: #007788;">function</span><span style="color: #000080;">&lt;</span>append_impl<span style="color: #000080;">&gt;</span> <span style="color: #0000ff;">const</span> append <span style="color: #000080;">=</span> append_impl<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Damit machen wir das struct append_impl zu einem Funktor, der unter dem Namen append zur Verfuegung steht. Die gesamte arrayDefinition Regel koennen wir dann folgendermassen schreiben:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">arrayDefinition
  <span style="color: #000080;">=</span>  lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'['</span><span style="color: #008000;">&#41;</span>     <span style="color: #008000;">&#91;</span>_val <span style="color: #000080;">=</span> new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">list</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
  <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">-</span><span style="color: #008000;">&#40;</span> double_   <span style="color: #008000;">&#91;</span>append<span style="color: #008000;">&#40;</span>_val, new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">atom</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>_1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span> <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #000040;">|</span> long_     <span style="color: #008000;">&#91;</span>append<span style="color: #008000;">&#40;</span>_val, new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">atom</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>_1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span> <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #000040;">|</span> bool_     <span style="color: #008000;">&#91;</span>append<span style="color: #008000;">&#40;</span>_val, new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">atom</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>_1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span> <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #000040;">|</span> string    <span style="color: #008000;">&#91;</span>append<span style="color: #008000;">&#40;</span>_val, new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">atom</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>_1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span> <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
      <span style="color: #008000;">&#41;</span>
  <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">']'</span>
  <span style="color: #008080;">;</span></pre></div></div>

<p>Diese Folge von Aktionen erzeugt also zunaechst ein neues Objekt vom Typ list und ruft dann fuer jedes Auftreten von double, long, bool oder string Werten den append Funktor auf, der dem list Objekt (in _val) ein neues atom anfuegt, dass in-place erzeugt wird. Wer sich nun fragt, warum wir das append vier Mal geschrieben haben, statt es einfach einmal hinter dem geklammerten Ausdruck zu verwenden, der moege bitte den Listenoperator am Ende der Zeilen beachten. Dieser fuehrt, zusammen mit dem &#8220;-&#8221; Operator fuer einen optionalen Ausdruck zu einem generierten Attribut mit komplexem Typ (optional< variant<...> >, siehe Beginn des Artikels), fuer das wir sicherlich keine append Funktion haetten schreiben wollen. Dadurch, dass wir die semantischen Aktionen direkt mit den POD Typen assoziieren, koennen wir einfach den Konstruktor von atom benutzen, um ein zugehoeriges Objekt zu erzeugen und fuegen dieses direkt in die Liste ein.</p>
<p>Die Regel listDefinition wird aehnlich implementiert, jedoch muessen wir in diesem Fall kein neues atom erzeugen, sondern koennen das generierte Attribut der Unterregel an den append Aufruf durchschleifen. Die genaue Implementierung ist dem vollstaendigen Sourcecode zu entnehmen.</p>
<p>Kommen wir zur groupDefinition: Hier muessen wir natuerlich zunaechst ein group Objekt erzeugen (wozu wir die lit Regel missbrauchen), und anschliessend saemtliche enthaltenen variableAssignments einfuegen. Hierbei habe ich mich fuer eine etwas andere Loesung entschieden, die ein vererbtes Attribut benutzt. Das bedeutet, dass eine Referenz auf eine lokale Variable an eine Subregel uebergeben wird, die das vererbte Attribut verwenden und ggf. auch modifizieren kann:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">groupDefinition
  <span style="color: #000080;">=</span>  lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'{'</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#91;</span>_val <span style="color: #000080;">=</span> new_<span style="color: #000080;">&lt;</span>cfg<span style="color: #008080;">::</span><span style="color: #007788;">group</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
  <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span> variableAssignment<span style="color: #008000;">&#40;</span>_val<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#41;</span>
  <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">'}'</span>
  <span style="color: #008080;">;</span></pre></div></div>

<p>Das Einfuegen der variableAssignments geschieht also nicht in der Regel groupDefinition, sondern in variableAssignment selbst. Die Regel file kann analog implementiert werden, allerdings haben wir hier kein lit zur Verfuegung, an dass wir die Erzeugung des group Objekts anheften koennen und muessen deshalb eine Dummyregel (eps) verwenden, die keinerlei Auswirkung auf die Grammatik hat (siehe Sourcecode).</p>
<p>Die letzte Regel, die wir genauer analysieren wollen, ist variableAssignment. Diese bekommt das bereits erwaehnte vererbte Attribut uebergeben (dessen Platzhalter _r1 heisst), und sieht so aus:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">variableAssignment
  <span style="color: #000080;">=</span>  literal            <span style="color: #008000;">&#91;</span>_a <span style="color: #000080;">=</span> _1<span style="color: #008000;">&#93;</span>
  <span style="color: #000080;">&gt;&gt;</span> <span style="color: #FF0000;">'='</span>
  <span style="color: #000080;">&gt;&gt;</span> <span style="color: #008000;">&#40;</span> groupDefinition  <span style="color: #008000;">&#91;</span>insert<span style="color: #008000;">&#40;</span>_r1, _a, _1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
     <span style="color: #000040;">|</span> listDefinition   <span style="color: #008000;">&#91;</span>insert<span style="color: #008000;">&#40;</span>_r1, _a, _1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
     <span style="color: #000040;">|</span> arrayDefinition  <span style="color: #008000;">&#91;</span>insert<span style="color: #008000;">&#40;</span>_r1, _a, _1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
     <span style="color: #000040;">|</span> atom             <span style="color: #008000;">&#91;</span>insert<span style="color: #008000;">&#40;</span>_r1, _a, _1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
     <span style="color: #008000;">&#41;</span>
  <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">';'</span>
  <span style="color: #008080;">;</span></pre></div></div>

<p>Der Funktor insert wird dabei aehnlich wie append implementiert. Um den Namen der Variablen zwischenzuspeichern, benutzen wir eine lokale Variable vom Typ string, deren Platzhalter _a ist (weitere lokale Variablen wuerden _b, _c, usw. heissen). Der Typ von _a muss in der Deklaration der Regel angegeben werden (siehe Sourcecode).</p>
<p>Damit haben wir unseren Parser komplettiert und koennen nun noch eine Klasse cfg_file schreiben, die das Oeffnen der Datei und die Verwendung des Parsers kapselt. Der vollstaendige Code inklusive einem kleinen Testprogramm kann hier heruntergeladen werden:</p>
<p><a href="http://www.johannes-asal.de/code/cfg_file_1_0.tar.gz">cfg_file library v1.0 (cfg_file_1_0.tar.gz)</a></p>
<p>Ich hoffe Ihnen hat dieses kleine Tutorial gefallen. Fuer weitere Fragen und Kritik oder Anregungen stehe ich gerne zur Verfuegung.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=179</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers mit Hilfe von boost::spirit (Teil 3b)</title>
		<link>http://www.johannes-asal.de/?p=171</link>
		<comments>http://www.johannes-asal.de/?p=171#comments</comments>
		<pubDate>Fri, 16 Apr 2010 11:21:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=171</guid>
		<description><![CDATA[Als letzten Schritt zur Vervollstaendigung unserer Klassenhierarchie wollen wir nun die Klasse element implementieren. Sie soll die folgenden Use Cases abdecken: Interpretation eines element Objekts als group, list oder atom Zugriff auf die Child Elemente ueber Key (Gruppe) oder Index (Array und Liste) Konvertierung eines Leaf Elements in einen der unterstuetzten Typen Lookup eines Leaf [...]]]></description>
			<content:encoded><![CDATA[<p>Als letzten Schritt zur Vervollstaendigung unserer Klassenhierarchie wollen wir nun die Klasse element implementieren. Sie soll die folgenden Use Cases abdecken:</p>
<ul>
<li>Interpretation eines element Objekts als group, list oder atom</li>
<li>Zugriff auf die Child Elemente ueber Key (Gruppe) oder Index (Array und Liste)</li>
<li>Konvertierung eines Leaf Elements in einen der unterstuetzten Typen</li>
<li>Lookup eines Leaf Elements ueber Pfadangabe und optionalen Defaultwert</li>
</ul>
<p>Der erste Punkt ist leicht zu realisieren. Wir schreiben drei Funktionen</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> group<span style="color: #000040;">&amp;</span> as_group<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">dynamic_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">const</span> group<span style="color: #000040;">&amp;</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">const</span> list<span style="color: #000040;">&amp;</span> as_list<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">dynamic_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">const</span> list<span style="color: #000040;">&amp;</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">const</span> atom<span style="color: #000040;">&amp;</span> as_atom<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">dynamic_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">const</span> atom<span style="color: #000040;">&amp;</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span></pre></div></div>

<p>Der dynamic_cast mit einer Objektreferenz sorgt dafuer, dass automatisch eine Exception geworfen wird, wenn das Objekt nicht vom gewuenschten Typ ist. Dies sollte vom Benutzer abgefangen werden.</p>
<p>Auch der Zugriff auf einzelne Childelemente per Key oder Index stellt kein grosses Problem dar. Wir definieren die Indexoperatoren</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> operator<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> key<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">return</span> this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>as_group<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">get</span><span style="color: #008000;">&#40;</span>key<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> operator<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">size_t</span> index<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">return</span> this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>as_list<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">get</span><span style="color: #008000;">&#40;</span>key<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Dabei setzen wir voraus, dass der Benutzer weiss, um welchen Typ es sich beim jeweiligen Element handelt und interpretieren es dementsprechend entweder als Gruppe oder Liste. Wird ein Operator auf einem ungeeigneten Datentyp aufgerufen, so werfen die as_group() bzw. as_list() Funktionen entsprechende Exceptions.</p>
<p>Falls es sich bei einem element Objekt um ein Leaf Element handelt, so muessen wir es in einen numerischen Typ oder String umwandeln koennen. Da wir bereits eine entsprechende Funktion in der atom Klasse definiert haben, koennen wir einfach durchschleifen:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">const</span> T as<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">return</span> this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>as_atom<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">as</span><span style="color: #000080;">&lt;</span>T<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Bleibt nur noch der Use Case des Wertelookups ueber eine Pfadangabe. Nehmen wir an, unsere Konfigurationsdatei sieht folgendermassen aus:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">app <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span>
  windows <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>
    <span style="color: #008000;">&#123;</span>
      title <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Fenster 1&quot;</span><span style="color: #008080;">;</span>
      width <span style="color: #000080;">=</span> <span style="color: #0000dd;">400</span><span style="color: #008080;">;</span>
      height <span style="color: #000080;">=</span> <span style="color: #0000dd;">300</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>,
    <span style="color: #008000;">&#123;</span>
      title <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Fenster 2&quot;</span><span style="color: #008080;">;</span>
      width <span style="color: #000080;">=</span> <span style="color: #0000dd;">600</span><span style="color: #008080;">;</span>
      heigh <span style="color: #000080;">=</span> <span style="color: #0000dd;">450</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
  <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Der Parser liefert uns ein Root Element, das wir r nennen wollen. Dann soll beispielsweise der Zugriff auf den height Wert des zweiten window Elements moeglich sein ueber</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">long</span> height <span style="color: #000080;">=</span> r.<span style="color: #007788;">lookup</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">long</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;app.windows[1].height&quot;</span>, <span style="color: #0000dd;">800</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>wobei 800 der Defaultwert ist, wenn die Option nicht gefunden wurde. Weiterhin wollen wir die folgende Syntax erlauben:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">long</span> height <span style="color: #000080;">=</span> r<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;app.windows[1].height&quot;</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">as</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">long</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Dazu muessen wir spaeter den bereits oben definierten operator[] geeignet anpassen. Implementieren wir aber zunaechst die lookup() Funktion:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> std<span style="color: #008080;">::</span><span style="color: #007788;">deque</span><span style="color: #000080;">&lt;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">variant</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span>, <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span> token_list<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">const</span> T lookup<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> path<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
<span style="color: #008000;">&#123;</span>
  token_list tokens <span style="color: #000080;">=</span> util<span style="color: #008080;">::</span><span style="color: #007788;">split</span><span style="color: #008000;">&#40;</span>path<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">return</span> recursive_lookup<span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">this</span>, tokens<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">as</span><span style="color: #000080;">&lt;</span>T<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> recursive_lookup<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> e, token_list tokens<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>tokens.<span style="color: #007788;">empty</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #0000ff;">return</span> e<span style="color: #008080;">;</span>
&nbsp;
  boost<span style="color: #008080;">::</span><span style="color: #007788;">variant</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span>, <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> t <span style="color: #000080;">=</span> tokens.<span style="color: #007788;">front</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  tokens.<span style="color: #007788;">pop_front</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> next<span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">apply_visitor</span><span style="color: #008000;">&#40;</span>visitor<span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span>, t<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">return</span> recursive_lookup<span style="color: #008000;">&#40;</span>next, tokens<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Wir splitten hier zunaechst den Pfadstring in eine Liste von Tokens, die den einzelnen Zugriffsbezeichnern entspricht (in unserem Beispiel also ["app", "windows", 1, "height"]). Anschliessend rufen wir die Funktion recursive_lookup() mit dem aktuellen Element als Ausgangspunkt auf, die rekursiv durch den Baum traversiert und das letzte Element zurueckliefert, das schliesslich als atom interpretiert und in den gewuenschten Typ konvertiert wird. Die Implementierung der Funktion split sowie der Fall mit Defaultwert ist dem vollstaendigen Quellcode zu entnehmen.</p>
<p>Passen wir abschliessend noch den operator[] an, um den gleichen Lookup Mechanismus auch in der Indexschreibweise zu ermoeglichen:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> operator<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> key<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>key.<span style="color: #007788;">find_first_of</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'.'</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #008080;">::</span><span style="color: #007788;">npos</span><span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    token_list tokens <span style="color: #000080;">=</span> util<span style="color: #008080;">::</span><span style="color: #007788;">split</span><span style="color: #008000;">&#40;</span>key<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> recursive_lookup<span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">this</span>, tokens<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
  <span style="color: #0000ff;">else</span>
    <span style="color: #0000ff;">return</span> this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>as_group<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">get</span><span style="color: #008000;">&#40;</span>key<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Damit haben wir nun alle folgenden (aequivalenten) Abfragemoeglichkeiten abgedeckt:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> title <span style="color: #000080;">=</span> r<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;app.windows[0].title&quot;</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">as</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> title <span style="color: #000080;">=</span> r<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;app&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;windows&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;title&quot;</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">as</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> title <span style="color: #000080;">=</span> r.<span style="color: #007788;">lookup</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;app.windows[0].title&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Mit Hilfe der im letzten Teil definierten Iteratoren koennen wir nun zum Beispiel auch ueber alle windows Elemente loopen und deren Eigenschaften ausgeben:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> cfg<span style="color: #008080;">::</span><span style="color: #007788;">list</span><span style="color: #000040;">&amp;</span> windows <span style="color: #000080;">=</span> r<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;app.windows&quot;</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">as_list</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
cfg<span style="color: #008080;">::</span><span style="color: #007788;">list</span><span style="color: #008080;">::</span><span style="color: #007788;">const_iterator</span> it1 <span style="color: #000080;">=</span> windows.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #008080;">;</span> it1 <span style="color: #000040;">!</span><span style="color: #000080;">=</span> windows.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it1<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">const</span> cfg<span style="color: #008080;">::</span><span style="color: #007788;">group</span><span style="color: #000040;">&amp;</span> properties <span style="color: #000080;">=</span> it1<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>as_group<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  cfg<span style="color: #008080;">::</span><span style="color: #007788;">group</span><span style="color: #008080;">::</span><span style="color: #007788;">const_iterator</span> it2 <span style="color: #000080;">=</span> properties.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #008080;">;</span> it2 <span style="color: #000040;">!</span><span style="color: #000080;">=</span> properties.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it2<span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> it2<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>first <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;: &quot;</span>
      <span style="color: #000080;">&lt;&lt;</span> it2<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>second<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>as<span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Die somit definierte Klassenstruktur ermoeglicht einen einfachen und effizienten Zugriff auf die Konfigurationsdaten, ist aber gleichzeitig noch ausreichend performant, um eine schnelle Erzeugung der Baumstruktur vom Parser aus zu gewaehrleisten. Die vollstaendige Implementierung kann <a href="http://www.johannes-asal.de/code/cfg_elements.h">hier</a> heruntergeladen werden.</p>
<p>Im naechsten und letzten Teil der Serie vervollstaendigen wir endlich unsere kleine Parser Bibliothek, indem wir semantische Aktionen zum Parser hinzufuegen, um den Parsetree zu erzeugen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=171</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers mit Hilfe von boost::spirit (Teil 3a)</title>
		<link>http://www.johannes-asal.de/?p=158</link>
		<comments>http://www.johannes-asal.de/?p=158#comments</comments>
		<pubDate>Tue, 13 Apr 2010 15:55:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=158</guid>
		<description><![CDATA[Nachdem wir in Teil 1 und 2 einen Parser fuer unser Konfigurationsformat erstellt haben, wollen wir nun eine geeignete Objektstruktur implementieren, die uns zum einen erlaubt, eine hierarchische In-Memory-Abbildung unseres Formats zu schaffen und die zum anderen moeglichst leicht mit Hilfe von semantischen Aktionen durch den Parser erstellt werden kann. Es gibt dabei prinzipiell mehrere [...]]]></description>
			<content:encoded><![CDATA[<p>Nachdem wir in Teil 1 und 2 einen Parser fuer unser Konfigurationsformat erstellt haben, wollen wir nun eine geeignete Objektstruktur implementieren, die uns zum einen erlaubt, eine hierarchische In-Memory-Abbildung unseres Formats zu schaffen und die zum anderen moeglichst leicht mit Hilfe von semantischen Aktionen durch den Parser erstellt werden kann.</p>
<p>Es gibt dabei prinzipiell mehrere Moeglichkeiten, wie vorgegangen werden kann. Meine erste Idee war, einen Baum aus polymorphen Objekten aufzubauen, der verschiedene Objekttypen fuer alle einzelnen Elemente der Konfigurationsstruktur enthaelt. Dies waere zwar fuer die Erstellung der Speicherstruktur durch den Parser am geeignetsten gewesen, haette jedoch den Benutzerzugriff auf die Daten unnoetig erschwert. In einem weiteren Prototyp waehlte ich als Datenstruktur einen monomorphen Baum aus nur einem einzigen Klassentyp, was allerdings Probleme bei der Abbildung der Hierarchie und der spaeteren Auswertung mit sich brachte.</p>
<p>Ich entschied mich daher fuer einen Kompromiss aus beiden Ansaetzen, bei dem ich die funktional gleichen Objekttypen zusammenfasse und in einen polymorphen Baum ueberfuehre. Intern wird dabei in Baum aus Zeigern erstellt (um eine hohe Performance zu gewaehrleisten), das externe Interface arbeitet jedoch ausschliesslich mit Objektreferenzen, so dass wir auch mit ueberladenen Operatoren arbeiten koennen.</p>
<p>Alle Konfigurationselemente erben gemeinsam von einer Klasse element, die wir zunaechst als leer definieren:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> element <span style="color: #008000;">&#123;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Wir werden erst spaeter Funktionalitaet zu element hinzufuegen, wenn wir das externe Interface definieren.</p>
<p>Im naechsten Schritt muessen wir die hierarchiegenerierenden Elemente auf Klassen abbilden. Unser Format erlaubt Gruppen, Listen und Arrays. Listen und Arrays haben das gleiche Interface, sie unterscheiden sich lediglich in den zugelassenen Typen ihrer Subelemente. Da wir fuer dieses Tutorial keine Ruecktransformation unserer Objekthierarchie in eine Konfigurationsdatei benoetigen, koennen wir Liste und Array als gleichwertig betrachten und in einen Typ (list) zusammenfassen. Die Gruppe unterscheidet sich hingegen funktional von Liste und Array und wird deshalb getrennt abgebildet (group):</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> group <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> element
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">void</span> insert<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> key, element<span style="color: #000040;">*</span> value<span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> key_<span style="color: #008000;">&#40;</span>key<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> settings_.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span>key_, value<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">ptr_map</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span>, element<span style="color: #000080;">&gt;</span> setting_map_t<span style="color: #008080;">;</span>
  setting_map_t settings_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> list <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> element
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">void</span> append<span style="color: #008000;">&#40;</span>element<span style="color: #000040;">*</span> value<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> settings_.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>value<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">ptr_vector</span><span style="color: #000080;">&lt;</span>element<span style="color: #000080;">&gt;</span> setting_list_t<span style="color: #008080;">;</span>
  setting_list_t setting_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Ich habe die insert bzw. append Funktionen absichtlich als private implementiert, da der Konfigurationsbaum fuer den Benutzer nicht modifizierbar sein soll. Den Parser werden wir spaeter als friend deklarieren.</p>
<p>Es fehlt nun nur noch eine Repraesentation der atomaren Elemente (Integer, Double, String und Bool). Wie bereits besprochen werden wir diese zu einer Klasse zusammenfassen:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> atom <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> element
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">explicit</span> atom<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">variant</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">bool</span>, <span style="color: #0000ff;">long</span>, <span style="color: #0000ff;">double</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #000040;">&amp;</span> value<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span>
    value_<span style="color: #008000;">&#40;</span>value<span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
  boost<span style="color: #008080;">::</span><span style="color: #007788;">variant</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">bool</span>, <span style="color: #0000ff;">long</span>, <span style="color: #0000ff;">double</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span> value_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Diese einfache Implementierung reicht bereits aus, um den Baum erzeugen zu koennen. Allerdings ist der Konfigurationsbaum recht nutzlos, wenn der Benutzer keine Moeglichkeit hat, diesen zu analysieren und einzelne Elemente zu extrahieren. Wir benoetigen also noch ein oeffentliches Interface, das uns eine Interaktion mit den Daten ermoeglicht.</p>
<p>Beginnen wir mit dem atom. Um auf den gekapselten Wert zugreifen zu koennen, koennten wir beispielsweise eine Funktion schreiben, die eine Kopie (oder konstante Referenz) des gespeicherten Variants zurueckgibt. Das hat jedoch den Nachteil, dass der Benutzer selbst boost::get aufrufen muss, um den Wert aus dem Variant zu extrahieren. Unser Ziel soll jedoch sein, die Verwendung der atom Klasse so transparent wie moeglich zu gestalten und die Implementierung nach aussen hin moeglichst zu verbergen. Daher fuegen wir besser der Klasse atom eine Funktion as() hinzu, die folgendermassen implementiert ist:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> atom <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> element
<span style="color: #008000;">&#123;</span>
  <span style="color: #666666;">// ...</span>
&nbsp;
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
  <span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> T<span style="color: #000080;">&gt;</span>
  <span style="color: #0000ff;">const</span> T as<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
  <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">apply_visitor</span><span style="color: #008000;">&#40;</span>atom_detail<span style="color: #008080;">::</span><span style="color: #007788;">visitor</span><span style="color: #000080;">&lt;</span>T<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, value_<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #666666;">// ...</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Die Aufgabe des hier verwendeten Visitors ist nicht nur die Extraktion des gewuenschten Typs aus dem Variant, sondern gleichzeitig eine Konvertierung der zulaessigen Werte untereinander, um zum Beispiel einen Double Wert auch als String extrahieren zu koennen. Die Implementierung des Visitors ist etwas umfangreicher und nicht sonderlich interessant, daher verweise ich diesbezueglich auf den Quellcode, der im Teil 3b verlinkt ist.</p>
<p>Betrachten wir als naechstes die Klasse group. Sie benoetigt zum einen ein Interface, um ueber die Subelemente iterieren zu koennen, zum anderen eine Moeglichkeit, direkt das zugehoerige Element zu einem beliebigen Key extrahieren zu koennen. Beides ist einfach zu realisieren:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> group <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> element
<span style="color: #008000;">&#123;</span>
  <span style="color: #666666;">// ...</span>
&nbsp;
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>  
  <span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> get<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> key<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
  <span style="color: #008000;">&#123;</span>
    setting_map_t<span style="color: #008080;">::</span><span style="color: #007788;">const_iterator</span> it <span style="color: #000080;">=</span> settings_.<span style="color: #007788;">find</span><span style="color: #008000;">&#40;</span>key<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>it <span style="color: #000080;">==</span> settings_.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
      <span style="color: #0000ff;">throw</span> std<span style="color: #008080;">::</span><span style="color: #007788;">runtime_error</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;element not found&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span>it<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>second<span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #0000ff;">typedef</span> setting_map_t<span style="color: #008080;">::</span><span style="color: #007788;">const_iterator</span> const_iterator<span style="color: #008080;">;</span>
  const_iterator begin<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> settings_.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
  const_iterator end<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> settings_.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #666666;">// ...</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Fuer list implementieren wir die Iteratoren analog, statt der get Funktion mit einem String Key schreiben wir jedoch ein get mit Index:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> list <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> element
<span style="color: #008000;">&#123;</span>
  <span style="color: #666666;">// ...</span>
&nbsp;
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
  <span style="color: #0000ff;">const</span> element<span style="color: #000040;">&amp;</span> get<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">size_t</span> index<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> settings_<span style="color: #008000;">&#91;</span>index<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #666666;">// ...</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Im naechsten Teil definieren wir das (umfangreichere) Interface fuer die Klasse element, die den zentralen Dreh- und Angelpunkt fuer den Zugriff auf die Konfigurationshierarchie darstellen wird.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=158</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers mit Hilfe von boost::spirit (Teil 2b)</title>
		<link>http://www.johannes-asal.de/?p=150</link>
		<comments>http://www.johannes-asal.de/?p=150#comments</comments>
		<pubDate>Wed, 31 Mar 2010 15:35:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=150</guid>
		<description><![CDATA[Im letzten Teil dieser Serie haben wir bereits einen Grossteil der Grammatik fuer unseren Parser definiert. Es fehlen nur noch die Definitionen der rekursiven Datenstrukturen Gruppe und Liste sowie des Arrays. Zunaechst wollen wir uns die Regel fuer den Array ansehen: arrayDefinition =      lit&#40;'['&#41; &#62;&#62; -&#40; double_ % ',' &#124; long_ % ',' &#124; bool_ [...]]]></description>
			<content:encoded><![CDATA[<p>Im letzten Teil dieser Serie haben wir bereits einen Grossteil der Grammatik fuer unseren Parser definiert. Es fehlen nur noch die Definitionen der rekursiven Datenstrukturen Gruppe und Liste sowie des Arrays. Zunaechst wollen wir uns die Regel fuer den Array ansehen:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">arrayDefinition
   <span style="color: #000080;">=</span>      lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'['</span><span style="color: #008000;">&#41;</span>
      <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">-</span><span style="color: #008000;">&#40;</span> double_ <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
          <span style="color: #000040;">|</span> long_ <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
          <span style="color: #000040;">|</span> bool_ <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
          <span style="color: #000040;">|</span> string <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
          <span style="color: #008000;">&#41;</span>
      <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">']'</span>
   <span style="color: #008080;">;</span></pre></div></div>

<p>Gemaess unserer Syntaxspezifikation wird der Array durch eine oeffnende eckige Klammer eingeleitet, gefolgt von beliebig vielen kommagetrennten Werten vom Typ double, long, bool oder string. Die schliessende eckige Klammer darf nie fehlen, daher kann der Parser auch sofort abbrechen, wenn keines der inneren Elemente mehr matcht und kein &#8220;]&#8221; folgt. Dies wird durch das einzelne &#8220;>&#8221; erreicht. Der Prozent Operator hinter einer Regel (X % C) bedeutet so viel wie &#8220;ein oder mehrere Produktionen vom Typ X, jeweils getrennt durch das Token C&#8221;. Das &#8220;-&#8221; (das fuer &#8220;optional&#8221; steht) sorgt dafuer, dass auch leere Arrays erlaubt sind.</p>
<p>Diese Regel beinhaltet noch eine weitere Besonderheit, die vielleicht auf den ersten Blick nicht ganz offensichtlich ist. Haetten wir fuer den inneren Teil geschrieben</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">double</span> <span style="color: #000040;">|</span> long_ <span style="color: #000040;">|</span> bool_ <span style="color: #000040;">|</span> string<span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span></pre></div></div>

<p>oder noch kuerzer</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">atom <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span></pre></div></div>

<p>so haetten wir zwar (mehr oder weniger) Zeichen gespart, aber die Semantik dieser Regel waere nicht mehr dieselbe. Der Array ist so definiert, dass er nur Elemente ein und desselben Typs enthalten darf. Wenn das erste Element ein String ist, so muessen alle weiteren Elemente auch Strings sein. Diese Eigenschaft ist aber nur garantiert, wenn wir den Listenoperator auf jede Unterregel fuer sich anwenden und erst die daraus resultierenden Regeln verodern.</p>
<p>Die Regel fuer die Liste sieht sehr aehnlich aus, muss aber zusaetzlich Rekursion erlauben. Im Gegensatz zum Array darf sie ausserdem gleichzeitig Elemente unterschiedlicher Typen enthalten:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">listDefinition
   <span style="color: #000080;">=</span>     lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'('</span><span style="color: #008000;">&#41;</span>
      <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">-</span><span style="color: #008000;">&#40;</span> <span style="color: #008000;">&#40;</span> groupDefinition
            <span style="color: #000040;">|</span> listDefinition
            <span style="color: #000040;">|</span> arrayDefinition
            <span style="color: #000040;">|</span> atom
            <span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span> <span style="color: #FF0000;">','</span>
          <span style="color: #008000;">&#41;</span>
      <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">')'</span>
   <span style="color: #008080;">;</span></pre></div></div>

<p>Wie schon beim Array besprochen muss der Listenoperator bei der inneren Regel nun aussen stehen, um Listeneintraege unterschiedlichen Typs zuzulassen. Erlaubte Produktionen innerhalb der Liste sind die Array- und Gruppendefinition, die Listendefinition (Rekursion!) sowie Elemente vom Typ atom.</p>
<p>Die Gruppendefinition ist die letzte Produktion, die uns noch fehlt. Sie ist im Wesentlichen der Liste aehnlich, enthaelt aber nicht nur eine Menge von Objektdefinitionen sondern vielmehr eine Liste von Variablenzuweisungen und bildet damit die Semantik eines Dictionaries (Key-Value-Map) in unserem Konfigurationsformat ab:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">groupDefinition
   <span style="color: #000080;">=</span>     lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'{'</span><span style="color: #008000;">&#41;</span>
      <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">*</span>variableAssignment
      <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">'}'</span>
   <span style="color: #008080;">;</span></pre></div></div>

<p>Innerhalb der geschweiften Klammern erlauben wir also eine beliebige Anzahl von Produktionen vom Typ &#8220;variableAssignment&#8221;, die wir bereits im Teil 2a definiert hatten.</p>
<p>Im naechsten Teil der Serie werden wir eine Objektstruktur definieren, die es uns erlaubt, Konfigurationsdateien geeignet abzubilden. Dabei werden wir insbesondere Wert darauf legen, dass der Zugriff auf die Konfigurationswerte moeglichst einfach und flexibel ist.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=150</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers mit Hilfe von boost::spirit (Teil 2a)</title>
		<link>http://www.johannes-asal.de/?p=107</link>
		<comments>http://www.johannes-asal.de/?p=107#comments</comments>
		<pubDate>Thu, 14 Jan 2010 11:50:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=107</guid>
		<description><![CDATA[Nachdem wir im ersten Teil das Format unserer Konfigurationsdateien definiert hatten, wollen wir heute einen Parser fuer dieses Format schreiben. Es waere prinzipiell moeglich, einen solchen Parser von Hand zu schreiben, allerdings ist die Spezifikation unserer Konfigurationssyntax bereits so komplex, dass wir sicherlich sehr lange brauchen wuerden, um eine funktionsfaehige und fehlerfreie Implementierung zu erhalten [...]]]></description>
			<content:encoded><![CDATA[<p>Nachdem wir im ersten Teil das Format unserer Konfigurationsdateien definiert hatten, wollen wir heute einen Parser fuer dieses Format schreiben. Es waere prinzipiell moeglich, einen solchen Parser von Hand zu schreiben, allerdings ist die Spezifikation unserer Konfigurationssyntax bereits so komplex, dass wir sicherlich sehr lange brauchen wuerden, um eine funktionsfaehige und fehlerfreie Implementierung zu erhalten (sofern wir nicht ueber langjaehrige Erfahrung in der Entwicklung von Parsern verfuegen). Daher greifen wir in diesem Beispiel auf einen sogenannten Parsergenerator zurueck.</p>
<p>Gewoehnliche Parsergeneratoren &#8212; wie zum Beispiel lex/yacc oder ANTLR &#8212; erwarten als Input eine Beschreibung der Syntax des zu parsenden Formats, die ueblicherweise in der Backus-Naur-Form (BNF) oder einer Erweiterung davon spezifiziert wird und die wir im Folgenden als Grammatik bezeichnen. Daraus erzeugt der Generator Code in der Zielsprache, der die Syntax analysiert und diese entweder in einen Syntaxbaum transformiert oder aber mit den Symbolen verknuepfte Aktionen ausfuehrt. Diese Separierung von Grammatik und generiertem Code hat den Vorteil, dass fuer verschiedene Zielsprachen ein und dieselbe Grammatik verwendet werden kann (sofern der Generator alle gewuenschten Zielsprachen unterstuetzt). Der Vorteil schmilzt jedoch dahin, sobald man semantische Aktionen verwenden will, da diese normalerweise bereits in der Grammatik angegeben werden und in der Zielsprache verfasst sein muessen.</p>
<p>Die boost Library bietet fuer C++ eine wesentlich bessere und elegantere Alternative: Den spirit Parser. Dieser verwendet Paradigmen des Template Metaprogramming, um eine Domain Specific Language auf dem C++ Syntaxraum zu definieren, die der BNF erstaunlich aehnlich ist. Was bedeutet das nun? Betrachten wir als Beispiel die Definition eines Symbols fuer ein if Konstrukt in der Sprache Pascal. In BNF wuerde man schreiben:</p>

<div class="wp_syntax"><div class="code"><pre class="bnf" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">&lt;</span><span style="color: #007;">if statement</span><span style="color: #000066; font-weight: bold;">&gt;</span> <span style="color: #000066; font-weight: bold;">::=</span> if <span style="color: #000066; font-weight: bold;">&lt;</span><span style="color: #007;">expression</span><span style="color: #000066; font-weight: bold;">&gt;</span> then <span style="color: #000066; font-weight: bold;">&lt;</span><span style="color: #007;">statement</span><span style="color: #000066; font-weight: bold;">&gt;</span> <span style="color: #000066; font-weight: bold;">|</span>
        if <span style="color: #000066; font-weight: bold;">&lt;</span><span style="color: #007;">expression</span><span style="color: #000066; font-weight: bold;">&gt;</span> then <span style="color: #000066; font-weight: bold;">&lt;</span><span style="color: #007;">statement</span><span style="color: #000066; font-weight: bold;">&gt;</span> else <span style="color: #000066; font-weight: bold;">&lt;</span><span style="color: #007;">statement</span><span style="color: #000066; font-weight: bold;">&gt;</span></pre></div></div>

<p>Die verwendeten Symbole &#8220;expression&#8221; und &#8220;statement&#8221; werden als bereits definiert vorausgesetzt. Uebertragen wir diese Regel in boost::spirit, so erhalten wir</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">if_statement <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;if&quot;</span> <span style="color: #000080;">&gt;&gt;</span> expression <span style="color: #000080;">&gt;&gt;</span> <span style="color: #FF0000;">&quot;then&quot;</span> <span style="color: #000080;">&gt;&gt;</span> statement
             <span style="color: #000040;">|</span> <span style="color: #FF0000;">&quot;if&quot;</span> <span style="color: #000080;">&gt;&gt;</span> expression <span style="color: #000080;">&gt;&gt;</span> <span style="color: #FF0000;">&quot;then&quot;</span> <span style="color: #000080;">&gt;&gt;</span> statement <span style="color: #000080;">&gt;&gt;</span> <span style="color: #FF0000;">&quot;else&quot;</span> <span style="color: #000080;">&gt;&gt;</span> statement<span style="color: #008080;">;</span></pre></div></div>

<p>Wir sehen, dass die Umsetzung der Grammatik in spirit fast eins zu eins der Backus Naur Form entspricht. Um den Syntaxregeln von C++ zu entsprechen, muessen wir allerdings die String Literale in Anfuehrungszeichen einschliessen und die einzelnen Elemente der Regel durch den Operator &#8220;>>&#8221; trennen (C++ erlaubt nicht die einfache Aneinanderreihung von Variablen ohne Verwendung von Operatoren zwischen den Variablen, weshalb in spirit der right shift Operator zu diesem Zweck ueberladen wurde). Regeln in spirit muessen zudem mit einem Semikolon abgeschlossen werden, da diese nichts anderes als gewoehnliche Variablenzuweisungen sind. Die Regel laesst sich mit Hilfe zusaetzlicher Operatoren noch vereinfachen zu</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">if_statement <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;if&quot;</span> <span style="color: #000080;">&gt;&gt;</span> expression <span style="color: #000080;">&gt;&gt;</span> <span style="color: #FF0000;">&quot;then&quot;</span> <span style="color: #000080;">&gt;&gt;</span> statement <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">-</span><span style="color: #008000;">&#40;</span> <span style="color: #FF0000;">&quot;else&quot;</span> <span style="color: #000080;">&gt;&gt;</span> statement <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Der Operator &#8220;-&#8221; macht den folgenden, in Klammern eingeschlossenen Ausdruck optional und erspart uns damit die in der vorherigen Version noch vorhandene zweite Regelvariante. Ein ausfuehrliches Benutzerhandbuch und ein Tutorial zu boost::spirit finden Sie unter <a href="http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/index.html">http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/index.html</a>.</p>
<p>Kommen wir zurueck zu unserem Konfigurationsformat. Wir werden nun eine Grammatik dafuer definieren, ueberspringen dabei aber den Zwischenschritt BNF und schreiben direkt gueltige spirit Regeln. Zunaechst benoetigen wir eine Regel, die die gesamte Datei repraesentiert. Eine Konfigurationsdatei besteht aus beliebig vielen Variablenzuweisungen, also definieren wir eine Regel</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">file <span style="color: #000080;">=</span> <span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span> variableAssignment <span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;&gt;</span> eoi<span style="color: #008080;">;</span></pre></div></div>

<p>Der Asterisk vor dem geklammerten Ausdruck steht fuer &#8220;beliebig viele&#8221;. Das abschliessende &#8220;eoi&#8221; steht fuer &#8220;end of input&#8221; und sorgt dafuer, dass sowohl Leerzeichen am Ende der Datei erlaubt sind und gleichzeitig der gesamte String gematcht wird (ansonsten koennte man in der Datei auch ungueltige Syntax verwenden, solange davor ein Teil steht, auf den das file Symbol passt).</p>
<p>Als naechstes muessen wir das Symbol &#8220;variableAssignment&#8221; definieren. Eine solche Variablenzuweisung besteht gemaess unserer Syntaxvorgaben aus einem Variablennamen gefolgt von einem Gleichheitszeichen und einer Variablendefinition:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">variableAssignment <span style="color: #000080;">=</span>
      literal
   <span style="color: #000080;">&gt;&gt;</span> <span style="color: #FF0000;">'='</span>
   <span style="color: #000080;">&gt;&gt;</span> <span style="color: #008000;">&#40;</span> groupDefinition
      <span style="color: #000040;">|</span> listDefinition
      <span style="color: #000040;">|</span> arrayDefinition
      <span style="color: #000040;">|</span> atom
      <span style="color: #008000;">&#41;</span>
   <span style="color: #000080;">&gt;</span>  <span style="color: #FF0000;">';'</span>
   <span style="color: #008080;">;</span></pre></div></div>

<p>Wir haben also festgelegt, dass eine Variablendefinition entweder eine &#8220;groupDefinition&#8221;, &#8220;listDefinition&#8221;, &#8220;arrayDefinition&#8221; oder ein &#8220;atom&#8221; sein kann. Um den Ausdruck abzuschliessen, fordern wir noch ein Semikolon am Ende, dass in diesem Fall nicht durch &#8220;>>&#8221; sondern durch &#8220;>&#8221; angehaengt wird, was dafuer sorgt, dass der Parser sofort einen Fehler wirft, wenn die vorherigen Symbole erfolgreich erkannt wurden, das Semikolon aber fehlt. Das letzte Semikolon dient wieder dazu, das eigentliche C++ Statement abzuschliessen und gehoert nicht zur Grammatik!</p>
<p>Das Symbol &#8220;literal&#8221; repraesentiert einen Variablennamen. Um gaengigen Programmiersprachenkonventionen zu folgen, erlauben wir hierfuer nur alphanumerische Zeichen und den Unterstrich &#8220;_&#8221;, und definieren zusaetzlich, dass das erste Zeichen keine Ziffer sein darf. Dies fuehrt uns auf folgende Regel:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">literal <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>alpha <span style="color: #000040;">|</span> <span style="color: #FF0000;">'_'</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span>alnum <span style="color: #000040;">|</span> <span style="color: #FF0000;">'_'</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Ein &#8220;literal&#8221; ist also ein Buchstabe oder ein Unterstrich gefolgt von beliebig vielen Buchstaben, Ziffern oder Unterstrichen. Beachten Sie bitte, dass nur die zweite Teilregel optional ist, der Variablenname muss also mindestens ein Zeichen lang sein (was Sinn macht).</p>
<p>Betrachten wir nun noch die Definition des Symbols &#8220;atom&#8221;, das wir wie folgt festlegen:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">atom <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>strict_double <span style="color: #000040;">|</span> long_ <span style="color: #000040;">|</span> bool_ <span style="color: #000040;">|</span> string<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>&#8220;long_&#8221; und &#8220;bool_&#8221; sind in spirit bereits eingebaute Parser, die, wie der Name schon suggeriert, long und bool Werte parsen. Das Symbol &#8220;string&#8221; wollen wir selbst definieren. Es sieht folgendermassen aus:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">string <span style="color: #000080;">=</span> lexeme<span style="color: #008000;">&#91;</span> lit<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">'&quot;'</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;&gt;</span> <span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span>char_ <span style="color: #000040;">-</span> <span style="color: #FF0000;">'&quot;'</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;</span> <span style="color: #FF0000;">'&quot;'</span> <span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Ein String in unserer Konfigurationsdatei muss also mit einem Anfuehrungszeichen beginnen, gefolgt von beliebig vielen Zeichen ausser dem Anfuehrungszeichen (char_ ist wieder ein eingebauter Parser und matcht jedes beliebige Zeichen), abgeschlossen von einem weiteren Anfuehrungszeichen.</p>
<p>Die Regel &#8220;strict_double&#8221; muessen wir noch definieren. Ein einfaches &#8220;double_&#8221; wuerde hier nicht wie gewuenscht funktionieren, da es auch Zahlen ohne Dezimalpunkt parst und damit der long_ Parser nie aufgerufen wuerde. Die Reihenfolge der Regeln umzukehren ist jedoch auch keine Loesung, da Floating Point Zahlen in der Regel mit einer Ziffer beginnen und daher die long_ Regel saemtliche Ziffern bis zum Dezimalpunkt konsumieren wuerde, waehrend die uebrigen Zeichen bis zum abschliessenden Semikolon nicht mehr in die Grammatik passen und somit einen Parser Fehler ausloesen wuerden. Wir koennen jedoch mit nur einer Zeile Code einen modifizierten double Parser definieren, der zwingend einen Dezimalpunkt voraussetzt:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">namespace</span> qi <span style="color: #000080;">=</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">spirit</span><span style="color: #008080;">::</span><span style="color: #007788;">qi</span><span style="color: #008080;">;</span>
qi<span style="color: #008080;">::</span><span style="color: #007788;">real_parser</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, qi<span style="color: #008080;">::</span><span style="color: #007788;">strict_real_policies</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span> strict_double<span style="color: #008080;">;</span></pre></div></div>

<p>Fehlen noch die Symbole &#8220;groupDefinition&#8221;, &#8220;listDefinition&#8221; und &#8220;arrayDefinition&#8221;. Diese sind umfangreicher, weshalb wir ihnen einen separaten Teil widmen wollen (2b).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=107</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Implementation eines Konfigurationsparsers mit Hilfe von boost::spirit (Teil 1)</title>
		<link>http://www.johannes-asal.de/?p=89</link>
		<comments>http://www.johannes-asal.de/?p=89#comments</comments>
		<pubDate>Mon, 30 Nov 2009 16:47:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=89</guid>
		<description><![CDATA[In der folgenden Serie von Artikeln beschaeftigen wir uns mit einer immer wiederkehrenden Aufgabenstellung der meisten C++ Programmierer: Der Entwicklung eines Parsers fuer Konfigurationsdateien. In meinen knapp 15 Jahren Programmierpraxis habe ich mindestens 10 verschiedene Parser fuer beinahe genauso viele verschiedene Konfigurationsformate geschrieben &#8212; vom simplen INI-Reader bis zum validierenden XML-Parser war alles dabei. Bezueglich [...]]]></description>
			<content:encoded><![CDATA[<p>In der folgenden Serie von Artikeln beschaeftigen wir uns mit einer immer wiederkehrenden Aufgabenstellung der meisten C++ Programmierer: Der Entwicklung eines Parsers fuer Konfigurationsdateien. In meinen knapp 15 Jahren Programmierpraxis habe ich mindestens 10 verschiedene Parser fuer beinahe genauso viele verschiedene Konfigurationsformate geschrieben &#8212; vom simplen INI-Reader bis zum validierenden XML-Parser war alles dabei. Bezueglich des Aufwands sind die beiden genannten Beispiele entgegengesetzte Extreme. INI Dateien lassen sich mit ein paar Zeilen Code einlesen und schreiben und mit geringem Mehraufwand auch in einen Objektbaum uebersetzen. XML hingegen verlangt dem Programmierer einiges an Disziplin und Schreibarbeit ab, um die umfangreichen DOM- bzw. SAX-Schnittstellen zu implementieren, insbesondere wenn man die komplette Spezifikation erfuellen will und gleichzeitig noch eine Validierung benoetigt.</p>
<p>Beide Formate &#8212; INI wie XML &#8212; sind ausserdem meines Erachtens fuer die Verwendung als Konfigurationsdateien denkbar ungeeignet. Waehrend XML dem Entwickler zwar alle Moeglichkeiten bietet, die Konfigurationen hierarchisch zu gliedern und beliebige Metadaten dazu abzuspeichern, ist die Verwendung von Begin- und Endtags doch in hoechstem Masse speicherineffizient und redundant. Weiterhin gibt das Format an sich keinerlei Typstruktur vor, weshalb diese entweder zusaetzlich auf das Format aufgesetzt oder vom Benutzer gehandhabt werden muss (dies hat natuerlich Vor- und Nachteile!). Wer nun glaubt, mit INI Dateien besser zu fahren, der wird schnell an Grenzen stossen. Lediglich eine einzige Hierarchieebene ist fuer die meisten Anwendungen zu wenig. Und auch hier gibt es ausser Strings keine vorgegebenen Typen.</p>
<p>Welche Anforderungen muss eine Konfigurationsdatei erfuellen, um moeglichst viele Anwendungsbereiche abzudecken? Fassen wir diese in einem kurzen Brainstorming zusammen:</p>
<ul>
<li>Unterstuetzung der wichtigsten atomaren Typen (int, float, bool, string)</li>
<li>Bereitstellung von Listen und Arrays als zusammengesetzte Datentypen (Listen koennen dabei beliebige Subelemente enthalten, Arrays hingegen sind homogene Felder atomarer Typen)</li>
<li>Einfuehrung unbegrenzter Hierarchieebenen durch Verwendung von assoziativen Arraystrukturen, die mehrere Variablendeklarationen zusammenfassen und rekursiv definiert werden koennen</li>
</ul>
<p>Damit haben wir Listen-, Array- und hierarchische Semantik gleichermassen abgedeckt und kommen damit schon sehr nahe an das XML Format heran. Bezueglich der Syntax des Formats habe ich mich an C++ bzw. Python angelehnt und fasse Listen in runden, Arrays in eckigen und assoziative Arrays in geschweiften Klammern zusammen. Ein Beispiel fuer eine solche Konfigurationsdatei ist im folgenden dargestellt:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">a <span style="color: #000080;">=</span> <span style="color: #0000dd;">5</span><span style="color: #008080;">;</span>
b <span style="color: #000080;">=</span> <span style="color:#800080;">6.5</span><span style="color: #008080;">;</span>
c <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span>
  var1 <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Hallo&quot;</span><span style="color: #008080;">;</span>
  pi <span style="color: #000080;">=</span> <span style="color:#800080;">3.14159</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
d <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>
  <span style="color: #008000;">&#123;</span> eins <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> zwei <span style="color: #000080;">=</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">;</span> drei <span style="color: #000080;">=</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>,
  <span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">2</span>, <span style="color: #0000dd;">3</span>, <span style="color: #0000dd;">4</span>, <span style="color: #0000dd;">5</span><span style="color: #008000;">&#93;</span>
<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Im naechsten Teil der Serie schreiben wir unter Zuhilfenahme der neuesten Version von boost::spirit (v2.1) einen Parser fuer das soeben definierte Format. Im dritten Teil werden wir eine Objektstruktur fuer die C++ API definieren und diese im letzten Teil mit dem Parser verknuepfen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=89</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rezension: Neue Jazz-Harmonielehre (Frank Sikora)</title>
		<link>http://www.johannes-asal.de/?p=86</link>
		<comments>http://www.johannes-asal.de/?p=86#comments</comments>
		<pubDate>Sun, 25 Oct 2009 20:48:47 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Musik]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=86</guid>
		<description><![CDATA[&#8220;Warum (noch) eine Harmonielehre?&#8221; fragt Frank Sikora in der Einleitung zu seinem Buch zu Recht. Eine Vielzahl von Büchern beschäftigt sich bereits ausführlich mit diesem Thema, und der interessierte Musiker mag der Meinung sein, dass sämtliche offenen Fragen in der bisherigen Literatur zufriedenstellend beantwortet werden. Leider deckt jedoch die intensive Beschäftigung mit Jazz, Improvisation und [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;Warum (noch) eine Harmonielehre?&#8221; fragt Frank Sikora in der Einleitung zu seinem Buch zu Recht. Eine Vielzahl von Büchern beschäftigt sich bereits ausführlich mit diesem Thema, und der interessierte Musiker mag der Meinung sein, dass sämtliche offenen Fragen in der bisherigen Literatur zufriedenstellend beantwortet werden. Leider deckt jedoch die intensive Beschäftigung mit Jazz, Improvisation und der Komposition im Allgemeinen Lücken im persönlichen Bild der Harmonielehre auf, die mit den üblichen Regeln und Tabellen, die viele Autoren offenbar als äußerst informativ und nachvollziehbar erachten, nicht gefüllt werden können. Ebenso fehlt in so gut wie allen Büchern ein adäquater Bezug zur musikalischen Praxis, der eigentlich im Mittelpunkt einer guten Harmonielehre stehen sollte. Was nützt das beste theoretische Wissen, wenn dieses nicht am Instrument oder Notenpapier umgesetzt werden kann?</p>
<p>Nach einem ersten Überfliegen des Buches steht fest: Dies ist nicht die durchschnittliche, anfängerkompatible Abhandlung über Harmonielehre. Hier werden auf den ersten 150 Seiten schon Themen behandelt, die in anderen Büchern nicht einmal im Anhang angesprochen werden. Wer nun glaubt, dass Sikora dafür weniger ins Detail geht als andere Autoren, der irrt: Jede noch so scheinbar unbedeutende Kleinigkeit wird genau erklärt und hervorragend motiviert. Selbst erfahrene Musiker werden erst beim Lesen dieses Buches verstehen, dass sie ganze Teilbereiche der Harmonielehre bisher schlichtweg nicht kannten.</p>
<p>Die Zielgruppe dieses Buches sind tatsächlich nur gut vorgebildete Musiker &#8211; Anfänger werden bereits nach den ersten 20 Seiten kapitulieren. Sikora macht es mit seinem hervorragenden Schreibstil und seinem zweifelsohne hervorragenden pädagogischen Talent dem interessierten Leser jedoch leicht, seinen Ausführungen zu folgen. Zahlreiche qualitativ hochwertige Notenbeispiele helfen, die harmonischen Zusammenhänge zu erfassen und zu verstehen.</p>
<p>Auf den ersten 40 Seiten werden die Grundlagen wie Tonsystem, Obertonreihe, Intervalle, Quintenzirkel und die Akkordsymbolschrift wiederholt. Weiter geht es mit detaillierten Ausführungen zu Modalität, Dur-Diatonik, Kadenzen, Skalen und ihre Beziehung zur Akkordsymbolik bis hin zu Modaler Harmonik und Modal Interchange. Bemerkenswert sind auch die mehr kompositorisch motivierten Kapitel zum musikalischen Motiv, Melodiebogen und harmonischen sowie melodischen Rhythmus.</p>
<p>Die verbleibenden 200 Seiten des Buches sind den Themen &#8220;Hören&#8221; und &#8220;Spielen&#8221; gewidmet und versuchen &#8211; soweit das mit einem Buch möglich ist &#8211; eine Beziehung zwischen dem inneren Ohr und dem Instrument herzustellen und sind nicht nur für Pianisten interessant. Auch das Kapitel zur Transkription ist hervorragend geschrieben und so ausführlich, dass keine Fragen offen bleiben dürften. Wer genug Eigenmotivation mitbringt, den werden Sikoras Ausführungen sicherlich einen großen Schritt weiterbringen.</p>
<p>Die Neue Jazz-Harmonielehre ist ein bemerkenswertes Buch &#8211; meines Erachtens sogar die beste Wahl zu diesem Thema &#8211; und sollte in keinem Bücherregal fehlen. Erfreulich ist auch der geringe Preis des Buches, das kaum mehr kostet als beispielsweise der hochgelobte Haunschild, der auf 150 Seiten jedoch sehr viele wichtige Themen auslässt und meiner Meinung nach vergleichsweise schlecht motiviert ist.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=86</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Embedding mit boost::python</title>
		<link>http://www.johannes-asal.de/?p=79</link>
		<comments>http://www.johannes-asal.de/?p=79#comments</comments>
		<pubDate>Fri, 27 Mar 2009 10:29:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://www.johannes-asal.de/?p=79</guid>
		<description><![CDATA[In vielen Fällen ist es wünschenswert, dem Benutzer einer Software die Möglichkeit zu geben, mittels einer Skriptsprache Erweiterungen zur Anwendung hinzuzufügen oder deren Laufzeitverhalten zu steuern oder zu ändern. Das Einbetten einer Skriptsprache in die Applikation ist allerdings kein einfaches Vorhaben, da Daten und Datenstrukturen zwischen den Sprachkontexten ausgetauscht werden müssen um der Skriptsprache Zugriff [...]]]></description>
			<content:encoded><![CDATA[<p>In vielen Fällen ist es wünschenswert, dem Benutzer einer Software die Möglichkeit zu geben, mittels einer Skriptsprache Erweiterungen zur Anwendung hinzuzufügen oder deren Laufzeitverhalten zu steuern oder zu ändern. Das Einbetten einer Skriptsprache in die Applikation ist allerdings kein einfaches Vorhaben, da Daten und Datenstrukturen zwischen den Sprachkontexten ausgetauscht werden müssen um der Skriptsprache Zugriff auf Objekte der Applikation zu ermöglichen und umgekehrt.</p>
<p>Dieser Artikel soll eine kurze Einführung in die Einbettung von Python in C++ Applikationen geben. Dabei wird die Library boost::python benutzt, die das Marshalling der Objekte erheblich vereinfacht (z.B. Kapselung der ansonsten notwendigen manuellen Verwaltung der Garbage Collection).</p>
</p>
<p>Betrachten wir ein sehr einfaches Python Modul mymodule.py mit nur einer einzigen Funktion:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> myfunction<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  c = <span style="color: #ff4500;">1234</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">5678</span>
  <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Result is'</span>, c</pre></div></div>

</p>
<p>Um diese Funktion aus einem C++ Kontext heraus aufzurufen, schreiben wir folgendes minimales Programm:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;boost/python/import.hpp&gt;</span>
<span style="color: #339900;">#include &lt;boost/python/call.hpp&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">python</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Py_Initialize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	object mymodule <span style="color: #000080;">=</span> import<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;mymodule&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	object dict <span style="color: #000080;">=</span> mymodule.<span style="color: #007788;">attr</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;__dict__&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	object func <span style="color: #000080;">=</span> dict<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;myfunction&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
	func<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	Py_Finalize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Die Aufrufe von Py_Initialize() und Py_Finalize() sind notwendig, um den eingebetteten Python Interpreter zu initialisieren bzw. sicher herunterzufahren. Im nächsten Schritt wird zunächst das Modul importiert, das Dictionary des Moduls geholt und schließlich eine Referenz auf die gewünschte Funktion erzeugt. Mit func() wird diese anschließend aufgerufen.</p>
<p>Durch die Verwendung von boost::python werden die zurückgelieferten PyObject Pointer in object Objekten gekapselt, die sich um die Garbage Collection kümmern. Dadurch spart man sich gegenüber der nativen Python API das manuelle Freigeben der Pointer mittels Py_DECREF().</p>
<p>Auf manchen Systemen (z.B. Linux) funktioniert der Aufruf jedoch nicht wie gewünscht, da der eingebettete Python Interpreter das Modul nicht findet. Der Grund dafür ist, dass der Pfad, in dem das C++ Programm ausgeführt wird, nicht automatisch als Suchpfad für Python Module hinzugefügt wird. Die Lösung für dieses Problem ist meines Wissens nicht dokumentiert und besteht einfach darin, mittels PySys_SetArgv(1, progName) einen beliebigen Namen für das Programm zu setzen (oder einfach die argc und argv Parameter der main Methode zu benutzen). Das komplette Programm sieht dann beispielsweise folgendermaßen aus:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;boost/python/import.hpp&gt;</span>
<span style="color: #339900;">#include &lt;boost/python/call.hpp&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">python</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Py_Initialize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> progName<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">const_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Embedded&quot;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
	PySys_SetArgv<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, progName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	object mymodule <span style="color: #000080;">=</span> import<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;mymodule&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	object dict <span style="color: #000080;">=</span> mymodule.<span style="color: #007788;">attr</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;__dict__&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	object func <span style="color: #000080;">=</span> dict<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;myfunction&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
	func<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	Py_Finalize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.johannes-asal.de/?feed=rss2&amp;p=79</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
