Library: complete implementation of code generation

...including the handling of cross jumps / links
...verified by one elaborate example in the tests
This commit is contained in:
Fischlurch 2024-03-24 21:42:38 +01:00
parent fd1ce5f0c1
commit 20f2b1b90a
3 changed files with 261 additions and 81 deletions

View file

@ -101,7 +101,8 @@
#include "lib/nocopy.hpp"
#include "lib/iter-index.hpp"
#include "lib/iter-explorer.hpp"
#include "lib/format-util.hpp"///////////////////OOO use format-string??
#include "lib/format-string.hpp"
#include "lib/format-util.hpp"
#include "lib/regex.hpp"
#include "lib/util.hpp"
@ -113,12 +114,14 @@
namespace lib {
namespace error = lumiera::error;
using std::optional;
using std::nullopt;
using std::string;
using StrView = std::string_view;
using util::_Fmt;
using util::unConst;
@ -183,7 +186,7 @@ namespace lib {
if ("for" == mat[4])
tag.syntax = mat[3].matched? TagSyntax::END_FOR : TagSyntax::FOR;
else
throw error::Logic("unexpected keyword");
throw error::Logic(_Fmt{"unexpected keyword \"%s\""} % mat[4]);
}
else
if (mat[2].matched)
@ -334,11 +337,60 @@ namespace lib {
void
compile (PAR& parseIter, ActionSeq& actions)
{
auto add = [&](Code c, string v){ actions.push_back (Action{c,v}); };
auto addCode = [&](Code c) { add ( c, parseIter->key); };
auto addLead = [&] { add (TEXT, string{parseIter->lead}); };
auto openScope = [&](Clause c){ scope_.push (ParseCtx{c, actions.size()});};
auto currIDX = [&]{ return actions.size(); };
auto valid = [&](Idx i){ return 0 < i and i < actions.size(); };
auto clause = [](Clause c)-> string { return c==IF? "if" : "for"; };
auto scopeClause = [&]{ return scope_.empty()? "??" : clause(scope_.top().clause); };
// Support for bracketing constructs (if / for)
auto beginIdx = [&]{ return scope_.empty()? 0 : scope_.top().begin; }; // Index of action where scope was opened
auto scopeKey = [&]{ return valid(beginIdx())? actions[beginIdx()].val : "";}; // Key controlling the if-/for-Scope
auto keyMatch = [&]{ return isnil(parseIter->key) or parseIter->key == scopeKey(); }; // Key matches in opening and closing tag
auto clauseMatch = [&](Clause c){ return not scope_.empty() and scope_.top().clause == c; }; // Kind of closing tag matches innermost scope
auto scopeMatch = [&](Clause c){ return clauseMatch(c) and keyMatch(); };
auto lead = [&]{ return parseIter->lead; };
auto clashLead = [&]{ return actions[scope_.top().after - 1].val; }; // (for diagnostics: lead before a conflicting other "else")
auto abbrev = [&](auto s){ return s.length()<16? s : s.substr(s.length()-15); }; // (shorten lead display to 15 chars)
// Syntax / consistency checks...
auto __checkBalanced = [&](Clause c)
{
if (not scopeMatch(c))
throw error::Invalid{_Fmt{"Unbalanced Logic: expect ${end %s %s}"
" -- found ...%s${end |↯|%s %s}"}
% scopeClause() % scopeKey()
% abbrev(lead())
% clause(c) % parseIter->key
};
};
auto __checkInScope = [&] {
if (scope_.empty())
throw error::Invalid{_Fmt{"Misplaced ...%s|↯|${else}"}
% abbrev(lead())};
};
auto __checkNoDup = [&] {
if (scope_.top().after != 0)
throw error::Invalid{_Fmt{"Conflicting ...%s${else} ⟷ ...%s|↯|${else}"}
% abbrev(clashLead()) % abbrev(lead())};
};
// Primitives used for code generation....
auto add = [&](Code c, string v){ actions.push_back (Action{c,v});};
auto addCode = [&](Code c) { add ( c, parseIter->key); }; // add code token and transfer key picked up by parser
auto addLead = [&] { add (TEXT, string{parseIter->lead}); }; // add TEXT token to represent the static part before this tag
auto openScope = [&](Clause c){ scope_.push (ParseCtx{c, currIDX()}); }; // start nested scope for bracketing construct (if / for)
auto closeScope = [&] { scope_.pop(); }; // close innermost nested scope
auto linkElseToStart = [&]{ actions[beginIdx()].refIDX = currIDX(); }; // link the start position of the else-branch into opening logic code
auto markJumpInScope = [&]{ scope_.top().after = currIDX(); }; // memorise jump before else-branch for later linkage
auto linkLoopBack = [&]{ actions.back().refIDX = scope_.top().begin; }; // fill in the back-jump position at loop end
auto linkJumpToNext = [&]{ actions[scope_.top().after].refIDX = currIDX(); }; // link jump to the position after the end of the logic bracket
auto hasElse = [&]{ return scope_.top().after != 0; }; // a jump code to link was only marked if there was an else tag
/* === Code Generation === */
switch (parseIter->syntax) {
case TagSyntax::ESCAPE:
addLead();
@ -354,31 +406,48 @@ namespace lib {
break;
case TagSyntax::END_IF:
addLead();
///////////////////////////////////////////////////OOO verify and pop IF-clause here
// if (scope_.empty() or
// (not isnil(tag.key) scope_.top())
__checkBalanced(IF);
if (hasElse())
linkJumpToNext();
else
linkElseToStart();
closeScope();
break;
case TagSyntax::FOR:
addLead();
openScope(FOR);
///////////////////////////////////////////////////OOO push FOR-clause here
addCode(ITER);
break;
case TagSyntax::END_FOR:
addLead();
///////////////////////////////////////////////////OOO verify and pop FOR-clause here
__checkBalanced(FOR);
if (hasElse())
linkJumpToNext();
else
{ // no else-branch; end active loop here
addCode(LOOP);
linkLoopBack();
linkElseToStart(); // jump behind when iteration turns out empty
}
closeScope();
break;
case TagSyntax::ELSE:
addLead();
if (true) /////////////////////////////////////////OOO derive IF or FOR from context
__checkInScope();
__checkNoDup();
if (IF == scope_.top().clause)
{
///////////////////////////////////////////////////OOO actual IF-else implementation
markJumpInScope();
addCode(JUMP);
linkElseToStart();
}
else
{
///////////////////////////////////////////////////OOO actual FOR-else implementation
addCode(LOOP);
linkLoopBack();
markJumpInScope();
addCode(JUMP);
linkElseToStart(); // jump to else-block when iteration turns out empty
}
break;
default:

View file

@ -236,6 +236,92 @@ for} tail...
)~";
auto actions = TextTemplate::ActionCompiler().buildActions(parse(input));
SHOW_EXPR(util::join (explore(actions).transform(render),"\n"))
CHECK (25 == actions.size());
CHECK (actions[ 0].code == TextTemplate::Code::TEXT);
CHECK (actions[ 0].val == "\n Prefix-1 "_expect); // static text prefix
CHECK (actions[ 0].refIDX == 0);
CHECK (actions[ 1].code == TextTemplate::Code::KEY); // a placeholder to be substituted
CHECK (actions[ 1].val == "some.key"_expect); // use "some.key" for data retrieval
CHECK (actions[ 2].code == TextTemplate::Code::TEXT); // static text between active fields
CHECK (actions[ 2].val == " next one is "_expect);
CHECK (actions[ 3].code == TextTemplate::Code::TEXT); // since next tag was escaped, it appears in static segment
CHECK (actions[ 3].val == "\\${escaped}\n Prefix-2 "_expect);
CHECK (actions[ 4].code == TextTemplate::Code::COND); // start of an if-bracket construct
CHECK (actions[ 4].val == "cond1"_expect); // data marked with "cond1" will be used to determine true/false
CHECK (actions[ 4].refIDX == 7 ); // IDX ≡ 7 marks start of the else-branch
CHECK (actions[ 5].code == TextTemplate::Code::TEXT); // this static block will only be included if "cond1" evaluates to true
CHECK (actions[ 5].val == " active "_expect);
CHECK (actions[ 6].code == TextTemplate::Code::JUMP); // unconditional jump at the end of the if-true-block
CHECK (actions[ 6].val == ""_expect);
CHECK (actions[ 6].refIDX == 8 ); // IDX ≡ 8 points to the next element after the conditional construct
CHECK (actions[ 7].code == TextTemplate::Code::TEXT); // this static (else)-block will be included if "cond1" does not hold
CHECK (actions[ 7].val == " inactive "_expect);
CHECK (actions[ 8].code == TextTemplate::Code::TEXT); // again a static segment, displayed unconditionally
CHECK (actions[ 8].val == "Prefix-3 "_expect); // Note: no newline, since the closing bracket was placed at line start
CHECK (actions[ 9].code == TextTemplate::Code::COND); // again a conditional (but this time without else-branch)
CHECK (actions[ 9].val == "cond2"_expect); // data marked with "cond2" will be evaluated as condition
CHECK (actions[ 9].refIDX == 11 ); // IDX ≡ 11 is the alternative route, this time pointing behind the conditional
CHECK (actions[10].code == TextTemplate::Code::TEXT); // static text block to be displayed as content of the conditional
CHECK (actions[10].val == " active2"_expect);
CHECK (actions[11].code == TextTemplate::Code::TEXT); // again an unconditional static segment (behind end of preceding conditional)
CHECK (actions[11].val == " more\n Prefix-4 "_expect);
CHECK (actions[12].code == TextTemplate::Code::ITER); // Start of a for-construct (iteration)
CHECK (actions[12].val == "data"_expect); // data marked with "data" will be used to find and iterate nested elements
CHECK (actions[12].refIDX == 23 ); // IDX ≡ 23 points to the alternative "else" block, in case no iteration takes place
CHECK (actions[13].code == TextTemplate::Code::TEXT); // static block to appear for each nested "data" element
CHECK (actions[13].val == " fixed "_expect);
CHECK (actions[14].code == TextTemplate::Code::KEY); // placeholder to be substituted
CHECK (actions[14].val == "embedded"_expect); // _typically_ the data "embedded" will live in the iterated, nested elements
CHECK (actions[15].code == TextTemplate::Code::TEXT); // again a static block, which however lives within the iterated segment
CHECK (actions[15].val == "\n Pre-5 "_expect);
CHECK (actions[16].code == TextTemplate::Code::COND); // a nested conditional, thus nested on second level within the iteration construct
CHECK (actions[16].val == "nested"_expect); // data marked with "nested" will control the conditional (typically from iterated data elements)
CHECK (actions[16].refIDX == 19 ); // IDX ≡ 19 points to the else-block of this nested conditional
CHECK (actions[17].code == TextTemplate::Code::TEXT); // static content to appear as nested if-true-section
CHECK (actions[17].val == "nested-active"_expect);
CHECK (actions[18].code == TextTemplate::Code::JUMP); // jump code at end of the true-section
CHECK (actions[18].val == ""_expect);
CHECK (actions[18].refIDX == 20 ); // IDX ≡ 20 points behind the end of this nested conditional construct
CHECK (actions[19].code == TextTemplate::Code::TEXT); // static content comprising the else-section
CHECK (actions[19].val == "nested-inactive"_expect); // Note: no whitespace due to placement of the tag brackets of "else" / "end if"
CHECK (actions[20].code == TextTemplate::Code::TEXT); // again an unconditional static segment, yet still within the looping construct
CHECK (actions[20].val == "loop-suffix"_expect);
CHECK (actions[21].code == TextTemplate::Code::LOOP); // the loop-end code, where evaluation will consider the next iteration
CHECK (actions[21].val == ""_expect);
CHECK (actions[21].refIDX == 12 ); // IDX ≡ 12 points back to the opening ITER code
CHECK (actions[22].code == TextTemplate::Code::JUMP); // if however the iteration is complete, evaluation will jump over the "else" section
CHECK (actions[22].val == ""_expect);
CHECK (actions[22].refIDX == 24 );
CHECK (actions[23].code == TextTemplate::Code::TEXT); // this static else-segment will appear whenever no iteration takes place
CHECK (actions[23].val == ""_expect); // Note: in this example there is an ${else}-tag, yet the content is empty
CHECK (actions[24].code == TextTemplate::Code::TEXT); // a final static segment after the last active tag
CHECK (actions[24].val == " tail...\n"_expect);
CHECK (actions[24].refIDX == 0);
}

View file

@ -112628,8 +112628,8 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710800049563" ID="ID_1822369135" MODIFIED="1710800055081" TEXT="Arbeitsprinzip">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1710800049563" ID="ID_1822369135" MODIFIED="1711311789300" TEXT="Arbeitsprinzip">
<icon BUILTIN="yes"/>
<node CREATED="1710800058362" ID="ID_1054523392" MODIFIED="1710800064259" TEXT="Phase-1 : parsing">
<node CREATED="1710800080064" ID="ID_849138431" MODIFIED="1710800099391" TEXT="Text einmal sequentiell dursuchen"/>
<node CREATED="1710800100004" ID="ID_1541936961" MODIFIED="1710800131459" TEXT="Marker-Tags suchen und extrahieren"/>
@ -112656,16 +112656,16 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710799898735" ID="ID_965266428" MODIFIED="1710799904120" TEXT="Datenstruktur">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710799920412" ID="ID_908650592" MODIFIED="1710800023758" TEXT="parsing">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710800526514" ID="ID_989913764" MODIFIED="1710805322868" TEXT="aufzubauender InstaceCode">
<node COLOR="#338800" CREATED="1710799898735" ID="ID_965266428" MODIFIED="1711311776315" TEXT="Datenstruktur">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1710799920412" ID="ID_908650592" MODIFIED="1711311774454" TEXT="parsing">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1710800526514" ID="ID_989913764" MODIFIED="1711311772980" TEXT="aufzubauender InstaceCode">
<arrowlink COLOR="#435183" DESTINATION="ID_983120521" ENDARROW="Default" ENDINCLINATION="115;-21;" ID="Arrow_ID_322992252" STARTARROW="None" STARTINCLINATION="129;12;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710800552767" ID="ID_1521047609" MODIFIED="1710800582043" TEXT="begleitender ClauseStack">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1710800552767" ID="ID_1521047609" MODIFIED="1711311771375" TEXT="begleitender ClauseStack">
<icon BUILTIN="button_ok"/>
<node CREATED="1710805340319" ID="ID_562049748" MODIFIED="1710809644676" TEXT="clause-IF">
<node CREATED="1710805427820" ID="ID_926529537" MODIFIED="1710805430543" TEXT="key"/>
<node CREATED="1710805433691" ID="ID_140538867" MODIFIED="1710805448452" TEXT="condIDX"/>
@ -112678,11 +112678,11 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710799932570" ID="ID_313850038" MODIFIED="1710799946174" TEXT="intance">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710800587002" ID="ID_983120521" MODIFIED="1710805322868" TEXT="abzuarbeitender InstanceCode">
<node COLOR="#338800" CREATED="1710799932570" ID="ID_313850038" MODIFIED="1711311764678" TEXT="intance">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1710800587002" ID="ID_983120521" MODIFIED="1711311769407" TEXT="abzuarbeitender InstanceCode">
<linktarget COLOR="#435183" DESTINATION="ID_983120521" ENDARROW="Default" ENDINCLINATION="115;-21;" ID="Arrow_ID_322992252" SOURCE="ID_989913764" STARTARROW="None" STARTINCLINATION="129;12;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1710800768234" ID="ID_59072753" MODIFIED="1710800773373" TEXT="Primitive">
<node CREATED="1710800778608" ID="ID_1425870712" MODIFIED="1710800781499" TEXT="text">
<node CREATED="1710801294036" ID="ID_321691659" MODIFIED="1710801330242" TEXT="content"/>
@ -112706,16 +112706,16 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710800605488" ID="ID_1639197274" MODIFIED="1710800613813" TEXT="begleitender ContextStack">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1710800605488" ID="ID_1639197274" MODIFIED="1711311767726" TEXT="begleitender ContextStack">
<icon BUILTIN="button_ok"/>
<node CREATED="1710802175845" ID="ID_838839444" MODIFIED="1710802179664" TEXT="State">
<node CREATED="1710802209121" ID="ID_1872142339" MODIFIED="1710802224187" TEXT="nested DataSrc"/>
<node CREATED="1710802225814" ID="ID_155578503" MODIFIED="1710802245296" TEXT="evaluationState"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710809327978" ID="ID_278831608" MODIFIED="1710809383069" TEXT="Implementierungs-Datentypen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1710809327978" ID="ID_278831608" MODIFIED="1711311760142" TEXT="Implementierungs-Datentypen">
<icon BUILTIN="button_ok"/>
<node CREATED="1710809339961" ID="ID_689101433" MODIFIED="1710809343260" TEXT="enum Clause"/>
<node CREATED="1710809343987" ID="ID_1483329962" MODIFIED="1710809347034" TEXT="enum Code"/>
<node CREATED="1710809347760" ID="ID_1225629738" MODIFIED="1710809361714" TEXT="struct ParseCtx"/>
@ -112733,8 +112733,8 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710799920412" ID="ID_1195498496" MODIFIED="1710800023758" TEXT="parsing">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1710804975672" ID="ID_1778438879" MODIFIED="1711211821132" TEXT="Reg-Exp-Iteration auf die Tag-Syntax">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1710804975672" ID="ID_1778438879" MODIFIED="1711311749543" TEXT="Reg-Exp-Iteration auf die Tag-Syntax">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1711211822654" FOLDED="true" ID="ID_1575734676" LINK="#ID_1871157756" MODIFIED="1711212214143" TEXT="Layer-1 : &#xdc;bersetzung in Syntax-F&#xe4;lle">
<icon BUILTIN="button_ok"/>
<node CREATED="1711212050899" ID="ID_573965593" MODIFIED="1711212112634" TEXT="gibt jeweils einen TagSyntax-Record aus">
@ -112758,16 +112758,16 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711211835240" ID="ID_1594550860" LINK="#ID_1703324697" MODIFIED="1711211884546" TEXT="Layer-2 : Behandeln und Ausfalten dieser F&#xe4;lle">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1711212223692" ID="ID_1386017379" MODIFIED="1711212229862" TEXT="ein custom-processing-Layer"/>
<node CREATED="1711212230571" ID="ID_1706127132" MODIFIED="1711212236414" TEXT="beinhaltet eine State-Machine"/>
<node COLOR="#338800" CREATED="1711211835240" FOLDED="true" ID="ID_1594550860" LINK="#ID_1703324697" MODIFIED="1711311747555" TEXT="Layer-2 : Behandeln und Ausfalten dieser F&#xe4;lle">
<icon BUILTIN="button_ok"/>
<node CREATED="1711212223692" ID="ID_1386017379" MODIFIED="1711311670232" TEXT="eine Compiler-Komponente die den Parser konsumiert"/>
<node CREATED="1711212230571" ID="ID_1706127132" MODIFIED="1711311716338" TEXT="beinhaltet einen situationsbezogenen Code-Generator"/>
<node CREATED="1711212237363" ID="ID_98431449" MODIFIED="1711212249045" TEXT="und einen Stack f&#xfc;r Klammer-Konstrukte"/>
<node CREATED="1711212252456" ID="ID_1957416037" MODIFIED="1711212264479" TEXT="pull-processing auf iterNext()"/>
<node CREATED="1711311730952" ID="ID_759274929" MODIFIED="1711311745908" TEXT="Verarbeitung in einem einzigen linearen Pass, incl. Querverlinkung"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710804999413" ID="ID_670708059" MODIFIED="1710805006332" TEXT="handzuhabende Situationen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1710804999413" ID="ID_670708059" MODIFIED="1711311634712" TEXT="handzuhabende Situationen">
<icon BUILTIN="button_ok"/>
<node CREATED="1710805054381" ID="ID_1600465677" MODIFIED="1710805058600" TEXT="erstes Tag">
<node COLOR="#435e98" CREATED="1710805070796" ID="ID_19487824" MODIFIED="1711231872228" TEXT="vorausgehenden Text als text-Code emittieren"/>
<node COLOR="#435e98" CREATED="1710805127396" ID="ID_1769703452" MODIFIED="1711231873849" TEXT="rekursiver Aufruf"/>
@ -112777,59 +112777,63 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
<node CREATED="1710805159120" ID="ID_966003839" MODIFIED="1710805161851" TEXT="if ID">
<node COLOR="#435e98" CREATED="1710805210794" ID="ID_1447898531" MODIFIED="1711231860504" TEXT="cond-Code mit key emittieren"/>
<node CREATED="1710805219728" ID="ID_373857285" MODIFIED="1710809681135" TEXT="push clause(IF)">
<node COLOR="#435e98" CREATED="1710805219728" ID="ID_373857285" MODIFIED="1711311602805" TEXT="push clause(IF)">
<node CREATED="1710805249556" ID="ID_1366141121" MODIFIED="1710805254583" TEXT="enth&#xe4;lt den Key"/>
<node CREATED="1710805255123" ID="ID_1075707089" MODIFIED="1710805271261" TEXT="enth&#xe4;lt den IDX des soeben emittierten Starters"/>
</node>
</node>
<node CREATED="1710805510953" ID="ID_1232635083" MODIFIED="1710809697061" TEXT="else &#x2227; Stack-Top &#x27fc; clause-IF">
<node CREATED="1710805771222" ID="ID_1862652580" MODIFIED="1710809703436" TEXT="Zugriff via clause-IF.condIDX"/>
<node CREATED="1710805749865" ID="ID_40408302" MODIFIED="1710805770154" TEXT="elseIDX in condCode schreiben"/>
<node CREATED="1710805869320" ID="ID_1903636142" MODIFIED="1711305325162" TEXT="aktuellen (else/jump)IDX in die clause-IF schreiben"/>
<node CREATED="1710805829022" ID="ID_495973445" MODIFIED="1710805843264" TEXT="jump-Code emittieren (jump-target leer)"/>
<node CREATED="1710805869320" ID="ID_1903636142" MODIFIED="1710809711798" TEXT="aktuellen (else/jump)IDX in die clause-IF schreiben"/>
<node CREATED="1710805749865" ID="ID_40408302" MODIFIED="1711306279428" TEXT="n&#xe4;chsten IDX nach jump in condCode schreiben">
<linktarget COLOR="#6c7778" DESTINATION="ID_40408302" ENDARROW="Default" ENDINCLINATION="156;0;" ID="Arrow_ID_254264341" SOURCE="ID_1525985296" STARTARROW="Default" STARTINCLINATION="156;0;"/>
</node>
</node>
<node CREATED="1710805928769" ID="ID_1002261040" MODIFIED="1710805938279" TEXT="end if ID">
<node CREATED="1710805952222" ID="ID_1751436972" MODIFIED="1710809716506" TEXT="pr&#xfc;fen: Stack-Top &#x27fc; clause-IF mit passender ID"/>
<node CREATED="1710806088475" ID="ID_1503372396" MODIFIED="1710809720258" TEXT="Zugriff via clause-IF.elseIDX">
<arrowlink COLOR="#6455aa" DESTINATION="ID_952557558" ENDARROW="Default" ENDINCLINATION="112;-9;" ID="Arrow_ID_1645155125" STARTARROW="None" STARTINCLINATION="103;11;"/>
</node>
<node CREATED="1710806120310" ID="ID_113535239" MODIFIED="1710806148751" TEXT="aktuell n&#xe4;chsten IDX in jump.afterIDX schreiben"/>
<node CREATED="1710806120310" ID="ID_113535239" MODIFIED="1711305502556" TEXT="aktuell n&#xe4;chsten IDX in jump.refIDX schreiben"/>
<node COLOR="#435e98" CREATED="1710806211723" ID="ID_544563630" MODIFIED="1711231882251" TEXT="(nichts zu emittieren)"/>
<node CREATED="1710806196725" ID="ID_1695937501" MODIFIED="1710806201560" TEXT="Stack pop"/>
<node COLOR="#435e98" CREATED="1710806196725" ID="ID_1695937501" MODIFIED="1711311615396" TEXT="Stack pop"/>
</node>
<node CREATED="1710807375799" ID="ID_952557558" MODIFIED="1710807485995" TEXT="end if ID &#x2227; elseIDX noch leer">
<linktarget COLOR="#6455aa" DESTINATION="ID_952557558" ENDARROW="Default" ENDINCLINATION="112;-9;" ID="Arrow_ID_1645155125" SOURCE="ID_1503372396" STARTARROW="None" STARTINCLINATION="103;11;"/>
<node CREATED="1710807400300" ID="ID_1849343250" MODIFIED="1710807950556" TEXT="Spezialfall &#x27f9; single-branch IF">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1710807616439" ID="ID_1525985296" MODIFIED="1710807629569" TEXT="aktuell n&#xe4;chsten IDX in cond.elseIDX schreiben "/>
<node CREATED="1710807616439" ID="ID_1525985296" MODIFIED="1711306293126" TEXT="aktuell n&#xe4;chsten IDX in cond.refIDX schreiben ">
<arrowlink COLOR="#6c7778" DESTINATION="ID_40408302" ENDARROW="Default" ENDINCLINATION="156;0;" ID="Arrow_ID_254264341" STARTARROW="Default" STARTINCLINATION="156;0;"/>
</node>
<node CREATED="1710807639284" ID="ID_1610786686" MODIFIED="1710807648431" TEXT="(nichts zu emittieren)"/>
<node CREATED="1710807649211" ID="ID_1724244138" MODIFIED="1710807651982" TEXT="Stack pop"/>
<node COLOR="#435e98" CREATED="1710807649211" ID="ID_1724244138" MODIFIED="1711311627321" TEXT="Stack pop"/>
</node>
<node CREATED="1710806240319" ID="ID_21539921" MODIFIED="1710806243387" TEXT="for ID">
<node COLOR="#435e98" CREATED="1710806265628" ID="ID_1120675972" MODIFIED="1711231886330" TEXT="iter-Code mit key emittieren"/>
<node CREATED="1710806276683" ID="ID_1007095460" MODIFIED="1710809759109" TEXT="push clause-FOR">
<node COLOR="#435e98" CREATED="1710806276683" ID="ID_1007095460" MODIFIED="1711311614171" TEXT="push clause-FOR">
<node CREATED="1710806367675" ID="ID_1074384173" MODIFIED="1710806371937" TEXT="enth&#xe4;lt den Key"/>
<node CREATED="1710806375389" ID="ID_1970731379" MODIFIED="1710806384327" TEXT="enth&#xe4;lt den IDX des soeben emittierten Starters"/>
</node>
</node>
<node CREATED="1710806405673" ID="ID_1310523006" MODIFIED="1710806408164" TEXT="else &#x2227; Stack-Top &#x27fc; clauseIT">
<node CREATED="1710806493641" ID="ID_1459454155" MODIFIED="1710809753965" TEXT="Zugriff via clause-FOR.iterIDX"/>
<node CREATED="1710806509686" ID="ID_1028209132" MODIFIED="1710806516550" TEXT="elseIDX in iterCode schreiben"/>
<node CREATED="1710806533512" ID="ID_1807003849" MODIFIED="1710806538211" TEXT="loop-Code emittieren"/>
<node CREATED="1710806552007" ID="ID_354718435" MODIFIED="1710809748470" TEXT="iterIDX aus der clause-FOR in den loop-Code &#xfc;bertragen"/>
<node CREATED="1710806552007" ID="ID_354718435" MODIFIED="1711305441229" TEXT="iterIDX aus der clause-FOR f&#xfc;r R&#xfc;cksprung in den loop-Code &#xfc;bertragen"/>
<node CREATED="1710808973802" ID="ID_21613324" MODIFIED="1710808986148" TEXT="jump-Code emittieren"/>
<node CREATED="1710806706513" ID="ID_899347616" MODIFIED="1710806717967" TEXT="(afterIDX) bleibt noch leer"/>
<node CREATED="1710806777807" ID="ID_700983662" MODIFIED="1710809774227" TEXT="aktuellen (jump)IDX in die clause-FOR schreiben"/>
<node CREATED="1710806509686" ID="ID_1028209132" MODIFIED="1711305413648" TEXT="n&#xe4;chsten IDX nach jump in iterCode schreiben"/>
</node>
<node CREATED="1710806821425" ID="ID_1990562028" MODIFIED="1710806827725" TEXT="end for ID">
<node CREATED="1710806838975" ID="ID_400001835" MODIFIED="1710809782658" TEXT="pr&#xfc;fen: Stack-Top &#x27fc; clause-FOR mit passender ID "/>
<node CREATED="1710806870554" ID="ID_1872952395" MODIFIED="1710809796838" TEXT="Zugriff via clause-FOR.loopIDX">
<arrowlink COLOR="#6c5999" DESTINATION="ID_905517349" ENDARROW="Default" ENDINCLINATION="116;-16;" ID="Arrow_ID_130125525" STARTARROW="None" STARTINCLINATION="108;10;"/>
</node>
<node CREATED="1710806926394" ID="ID_1821893125" MODIFIED="1710806947252" TEXT="aktuell n&#xe4;chsten IDX in loop.afterIDX schreiben"/>
<node CREATED="1710806926394" ID="ID_1821893125" MODIFIED="1711305490718" TEXT="aktuell n&#xe4;chsten IDX in jump.refIDX schreiben"/>
<node COLOR="#435e98" CREATED="1710807230043" ID="ID_877544642" MODIFIED="1711234256941" TEXT="(nichts zu emittieren)"/>
<node CREATED="1710807235490" ID="ID_598110285" MODIFIED="1710807239243" TEXT="Stack pop"/>
<node COLOR="#435e98" CREATED="1710807235490" ID="ID_598110285" MODIFIED="1711311617659" TEXT="Stack pop"/>
</node>
<node CREATED="1710807760468" ID="ID_905517349" MODIFIED="1710809796838" TEXT="end for ID &#x2227; loopIDX noch leer">
<linktarget COLOR="#6c5999" DESTINATION="ID_905517349" ENDARROW="Default" ENDINCLINATION="116;-16;" ID="Arrow_ID_130125525" SOURCE="ID_1872952395" STARTARROW="None" STARTINCLINATION="108;10;"/>
@ -112840,11 +112844,11 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<node CREATED="1710808688599" ID="ID_1119725509" MODIFIED="1710809807726" TEXT="Zugriff via clause-FOR.iterIDX"/>
<node CREATED="1710808120500" ID="ID_168022679" MODIFIED="1710809815174" TEXT="iterIDX aus der clause-FOR in den loop-Code &#xfc;bertragen "/>
<node CREATED="1710808166910" ID="ID_1300637456" MODIFIED="1710809030190" TEXT="(keinen weiteren jump-Code emittieren)"/>
<node CREATED="1710807235490" ID="ID_1468993776" MODIFIED="1710807239243" TEXT="Stack pop"/>
<node COLOR="#435e98" CREATED="1710807235490" ID="ID_1468993776" MODIFIED="1711311629148" TEXT="Stack pop"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710799932570" ID="ID_1103663065" MODIFIED="1710799946174" TEXT="intance">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710799932570" ID="ID_1103663065" MODIFIED="1710799946174" TEXT="instance">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710800667346" ID="ID_299824445" MODIFIED="1710800700515" TEXT="handzuhabende Situationen">
<icon BUILTIN="flag-yellow"/>
@ -113060,19 +113064,30 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1710856784967" ID="ID_201927694" MODIFIED="1711067618760" TEXT="Parsing soll eager sein (wegen Syntax-Fehlern)">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1711057133538" ID="ID_1870486170" MODIFIED="1711128087871" TEXT="versuche aber trotzdem ein Pipeline-Design">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1711057133538" ID="ID_1870486170" MODIFIED="1711312266549" TEXT="versuche aber trotzdem ein Pipeline-Design">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
naja...
</p>
<p>
Hat teilweise schon was gebracht, denn der Parser ist sch&#246;n kompakt und klar geworden &#8212; aber f&#252;r den Compiler <i>bin ich genau deshalb in den Urwald geraten </i>&#8212; das war eine &#8222;schwere Geburt&#8220; &#8212; und in mehreren Schritten bin ich letztlich bei einer funktional-imperativen Formulierung angekommen, die jetzt einigerma&#223;en gut lesbar ist...
</p>
</body>
</html></richcontent>
<icon BUILTIN="button_cancel"/>
<node CREATED="1711057187292" ID="ID_1474035866" MODIFIED="1711057203717" TEXT="weil die Verarbeitung eigentlich linear und lokal ist"/>
<node CREATED="1711057204665" ID="ID_1095373221" MODIFIED="1711057311262" TEXT="d.h. man m&#xfc;&#xdf;te jeweils nur einen Match betrachten..."/>
<node CREATED="1711057311970" ID="ID_1246349032" MODIFIED="1711057341273" TEXT="das wird aber schwierig: man br&#xe4;uchte einen Buffer mit allem Content seit dem letzten Match"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1711128045349" ID="ID_1871157756" MODIFIED="1711128084612" TEXT="eine State-Core die die Klassifikation des aktuellen Match repr&#xe4;sentiert">
<node COLOR="#435e98" CREATED="1711128045349" ID="ID_1871157756" MODIFIED="1711312024109" TEXT="eine State-Core die die Klassifikation des aktuellen Match repr&#xe4;sentiert">
<icon BUILTIN="idea"/>
<node CREATED="1711128102358" ID="ID_1461727407" MODIFIED="1711128105913" TEXT="TagSyntax"/>
<node CREATED="1711128106645" ID="ID_1902297931" MODIFIED="1711128116511" TEXT="ein Enum Keyword "/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1711128122683" ID="ID_1243841516" MODIFIED="1711157950184" TEXT="&#xdc;bersetzung Match-Result &#x27fc; Keyword">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711158542348" ID="ID_1852280497" MODIFIED="1711158550267" TEXT="Escape ist ein Spezialfall">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1711128122683" ID="ID_1243841516" MODIFIED="1711312036282" TEXT="&#xdc;bersetzung Match-Result &#x27fc; Keyword">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1711158542348" ID="ID_1852280497" MODIFIED="1711312034846" TEXT="Escape ist ein Spezialfall">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1711158551561" ID="ID_1259756840" MODIFIED="1711158568512" TEXT="Key-Feld stets f&#xfc;llen wenn der betr. Match was greift">
<icon BUILTIN="button_ok"/>
@ -113087,7 +113102,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1711157966472" ID="ID_1217654924" MODIFIED="1711157971727" TEXT="Probleme">
<node COLOR="#435e98" CREATED="1711157966472" ID="ID_1217654924" MODIFIED="1711312029156" TEXT="Probleme">
<icon BUILTIN="messagebox_warning"/>
<node COLOR="#338800" CREATED="1711157973839" ID="ID_379810737" MODIFIED="1711158003619" TEXT="brauche ein &#xbb;schleppendes Pr&#xe4;fix&#xab;">
<icon BUILTIN="button_ok"/>
@ -113156,17 +113171,21 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1711158657004" ID="ID_1183584439" MODIFIED="1711158688520" TEXT="Vorsicht: string-view ist gef&#xe4;hrlich &#x2014; wirklich sinnvoll?">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1711158657004" ID="ID_1183584439" MODIFIED="1711312008687" TEXT="Vorsicht: string-view ist gef&#xe4;hrlich &#x2014; wirklich sinnvoll?">
<icon BUILTIN="help"/>
<node CREATED="1711158703398" ID="ID_338603175" MODIFIED="1711211670624" TEXT="in den Command-Tokens werden ohnehin Strings gespeichert"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711158747109" ID="ID_514130753" MODIFIED="1711158769304" TEXT="nochmal explizit durchverfolgen wo &#xbb;materialisiert&#xab; werden soll">
<node COLOR="#435e98" CREATED="1711158747109" ID="ID_514130753" MODIFIED="1711312002712" TEXT="nochmal explizit durchverfolgen wo &#xbb;materialisiert&#xab; werden soll">
<icon BUILTIN="yes"/>
<node CREATED="1711311915686" ID="ID_305977128" MODIFIED="1711311941523" TEXT="&#xd83e;&#xdc32; in der Code-Generierung"/>
<node CREATED="1711311942776" ID="ID_610363690" MODIFIED="1711311959105" TEXT="sinnvoll da der Template-Input-Text nicht gespeichert werden mu&#xdf;"/>
<node CREATED="1711311959909" ID="ID_1517686369" MODIFIED="1711311977790" TEXT="dagegen die Action-Codes allozieren wir ohnehin"/>
<node CREATED="1711311978690" ID="ID_813944433" MODIFIED="1711312000104" TEXT="da macht es Sinn, die jeweils zugeschnittenen Teilstrings mit auf den Heap zu schreiben"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711211350569" ID="ID_1703324697" MODIFIED="1711211362297" TEXT="&#xdc;bersetzung in eine Action-Sequenz">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1711211369094" ID="ID_381376485" MODIFIED="1711211681159" TEXT="Achtung: mu&#xdf; die Iteration &#xbb;rekursiv auffalten&#xab;">
<node COLOR="#338800" CREATED="1711211350569" ID="ID_1703324697" MODIFIED="1711312275358" TEXT="&#xdc;bersetzung in eine Action-Sequenz">
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1711211369094" ID="ID_381376485" MODIFIED="1711312056608" TEXT="Achtung: mu&#xdf; die Iteration &#xbb;rekursiv auffalten&#xab;">
<linktarget COLOR="#8a7986" DESTINATION="ID_381376485" ENDARROW="Default" ENDINCLINATION="59;-62;" ID="Arrow_ID_1443688910" SOURCE="ID_649407235" STARTARROW="None" STARTINCLINATION="-219;8;"/>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1711211412952" ID="ID_1907051261" MODIFIED="1711211437713" TEXT="in diversen F&#xe4;llen erzeugt ein parse-Match mehrere Action-Token"/>
@ -113175,15 +113194,15 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711212348956" ID="ID_363295345" MODIFIED="1711283010871" TEXT="pull-processing-Layer schaffen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1711212348956" ID="ID_363295345" MODIFIED="1711312149190" TEXT="parse-and-compile-Layer schaffen">
<icon BUILTIN="button_ok"/>
<node CREATED="1711212365801" ID="ID_537344075" MODIFIED="1711212378412" TEXT="dieser enth&#xe4;lt die eigentliche compile-Logik"/>
<node CREATED="1711212381344" ID="ID_1526201544" MODIFIED="1711212412343" TEXT="&#x27f9; wird eine nested template in der eigentlichen Engine"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711212414388" ID="ID_21802142" MODIFIED="1711212493609" TEXT="mu&#xdf; &#xbb;State-Core&#xab;-Konzept implementieren &#x2014; Behandlung h&#xe4;ngt an iterNext()">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#5b280f" CREATED="1711212414388" ID="ID_21802142" MODIFIED="1711312067983" TEXT="mu&#xdf; &#xbb;State-Core&#xab;-Konzept implementieren &#x2014; Behandlung h&#xe4;ngt an iterNext()">
<icon BUILTIN="button_cancel"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1711218612775" ID="ID_1789122488" MODIFIED="1711218978734" TEXT="State-Machine implementieren">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1711218612775" ID="ID_1789122488" MODIFIED="1711312073000" TEXT="State-Machine implementieren">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1711218621758" ID="ID_441666770" MODIFIED="1711218632180" TEXT="Funktion compile()">
<icon BUILTIN="info"/>
</node>
@ -113229,16 +113248,19 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1711218958736" ID="ID_263202088" MODIFIED="1711237473886" TEXT="Klammer-Konstrukte">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1711218958736" ID="ID_263202088" MODIFIED="1711312074588" TEXT="Klammer-Konstrukte">
<icon BUILTIN="button_ok"/>
<node CREATED="1711231460288" ID="ID_882106671" LINK="#ID_966003839" MODIFIED="1711231525159" TEXT="IF"/>
<node CREATED="1711231463976" ID="ID_1802146457" LINK="#ID_21539921" MODIFIED="1711231507080" TEXT="FOR"/>
</node>
<node COLOR="#435e98" CREATED="1711312099514" ID="ID_589436817" MODIFIED="1711312114725" TEXT="verwende Kurzschreibweise mit vielen Hilfs-Lambdas">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1711237221184" ID="ID_838370074" MODIFIED="1711237227436" TEXT="Fehlerbehandlung">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711237228696" ID="ID_1920021000" MODIFIED="1711237271250" TEXT="unbalancierte Konstrukte">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1711237228696" ID="ID_1920021000" MODIFIED="1711312079978" TEXT="unbalancierte Konstrukte">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711237235134" ID="ID_889276068" MODIFIED="1711237271250" TEXT="komplett leere Tags">
<icon BUILTIN="flag-yellow"/>
@ -113249,7 +113271,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1711245155902" ID="ID_1602057321" MODIFIED="1711245176070" TEXT="Problem: ID-Querverlinkung in der Pipeline">
<node COLOR="#435e98" CREATED="1711245155902" ID="ID_1602057321" MODIFIED="1711312279045" TEXT="Problem: ID-Querverlinkung in der Pipeline">
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1711245177524" ID="ID_1786845265" MODIFIED="1711282922187" TEXT="problematisch, da der Ziel-Container noch gar nicht existiert">
<icon BUILTIN="broken-line"/>
@ -113281,6 +113303,9 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<arrowlink COLOR="#b72676" DESTINATION="ID_431240403" ENDARROW="Default" ENDINCLINATION="-189;13;" ID="Arrow_ID_232745747" STARTARROW="None" STARTINCLINATION="170;-14;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
<node COLOR="#338800" CREATED="1711312290872" ID="ID_473619294" MODIFIED="1711312308985" TEXT="Ausf&#xfc;hrliches Beispiel mit allen erwarteten Action-codes und Quer-Indices">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1711057942703" ID="ID_1535269781" MODIFIED="1711067611692" TEXT="Regular-Expression entwickeln">
@ -113378,8 +113403,8 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
<node COLOR="#338800" CREATED="1711237148285" ID="ID_1097637346" MODIFIED="1711237174630" TEXT="Syntax-Keyword-Erkennung">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1711237159112" ID="ID_292718692" MODIFIED="1711237172936" TEXT="Compilation in Action-Sequenz">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1711237159112" ID="ID_292718692" MODIFIED="1711312317352" TEXT="Compilation in Action-Sequenz">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1711237177758" ID="ID_428622943" MODIFIED="1711237184293" TEXT="Parse-Fehler">
<icon BUILTIN="flag-pink"/>