Library: integrate repeated clauses into the DSL

Meanwhile, some kind of style scheme has emerged for the DSL:
We're working much with postfix-decorating operators, which
augment or extend the ''whole syntax clauses defined thus far''

In accordance with this scheme, I decided also to treat repeated expression
as a postfix operator (other than initially planned). This means, the actual
body to be repeated is ''the syntax clause defined thus far'', and the
repeat()-operator only details the number of repetitions and an optional delimiter.
This commit is contained in:
Fischlurch 2025-01-22 22:31:25 +01:00
parent 6dc2561262
commit 5fed95b929
3 changed files with 235 additions and 70 deletions

View file

@ -27,7 +27,9 @@
#define LIB_PARSE_H
#include "lib/error.hpp"
#include "lib/branch-case.hpp"
#include "lib/format-string.hpp"
#include "lib/meta/variadic-rebind.hpp"
#include "lib/meta/function.hpp"
#include "lib/meta/trait.hpp"
@ -41,6 +43,7 @@
namespace util {
namespace parse {
namespace err = lumiera::error;
using std::move;
using std::forward;
@ -52,11 +55,14 @@ namespace util {
using std::decay_t;
using std::tuple;
using std::array;
using util::_Fmt;
using StrView = std::string_view;
/**
* Parse evaluation result
* @tparam RES model type to bind
*/
template<class RES>
struct Eval
@ -240,15 +246,16 @@ namespace util {
/** Special case Product Model to represent iterative sequence */
template<typename RES>
struct IterModel
: std::vector<RES>
{
RES& get (size_t i) { return this->at(i); }
};
/** Marker-Tag for the result from a sub-expression, not to be joined */
template<typename RES>
struct SubModel
{
RES model;
};
/** Standard case : combinator of two model branches */
@ -282,12 +289,6 @@ namespace util {
using Result = TAG<R1,R2>;
};
/** Special Case : absorb further similar elements into IterModel */
template<class RES>
struct _Join<IterModel, IterModel<RES>, RES>
{
using Result = IterModel<RES>;
};
/** accept sequence of two parse functions */
@ -359,6 +360,49 @@ namespace util {
}
/** repeatedly accept parse-function, optionally delimited. */
template<class C1, class C2>
auto
repeatedConnex (uint min, uint max
,C1&& bodyConnex, C2&& delimConnex)
{
using Res = typename decay_t<C1>::Result;
using IterResult = IterModel<Res>;
using IterEval = Eval<IterResult>;
return Connex{[sep = forward<C2>(delimConnex)
,body = forward<C1>(bodyConnex)
,min,max
]
(StrView toParse) -> IterEval
{
uint consumed{0};
IterResult results;
do
{
uint offset{0};
if (not results.empty())
{ // look for delimiter within sequence
auto delim = sep.parse (toParse);
if (not delim.result)
break;
offset += delim.consumed;
}
auto eval = body.parse (toParse.substr(offset));
if (not eval.result)
break;
offset += eval.consumed;
results.emplace_back (move(*eval.result));
toParse = toParse.substr(offset);
consumed += offset;
}
while (results.size() < max);
return results.size() >= min? IterEval{move(results), consumed}
: IterEval{std::nullopt};
}};
}
template<class PAR>
class Syntax;
@ -424,10 +468,11 @@ using Sigi = typename _Fun<PFun>::Sig;
using Connex = typename PAR::Connex;
using Result = typename PAR::Result;
bool success() const { return bool(Syntax::result); }
bool hasResult() const { return bool(Syntax::result); }
Result& getResult() { return * Syntax::result; }
Result&& extractResult(){ return move(getResult()); }
bool success() const { return bool(Syntax::result); }
bool hasResult() const { return bool(Syntax::result); }
size_t consumed() const { return Eval<Result>::consumed;}
Result& getResult() { return * Syntax::result; }
Result&& extractResult(){ return move(getResult()); }
Syntax()
: parse_{NullType()}
@ -457,6 +502,9 @@ using Sigi = typename _Fun<PFun>::Sig;
return parse_;
}
/** ===== Syntax clause builder DSL ===== */
template<typename SPEC>
auto
seq (SPEC&& clauseDef)
@ -475,14 +523,47 @@ using Sigi = typename _Fun<PFun>::Sig;
,Parser{forward<SPEC> (clauseDef)}));
}
private:
Eval<Result>&
eval()
auto
repeat(uint cnt =uint(-1))
{
return *this;
return repeat (1,cnt, NullType{});
}
template<typename SPEC>
auto
repeat (SPEC&& delimDef)
{
return repeat (1,uint(-1), forward<SPEC> (delimDef));
}
template<typename SPEC>
auto
repeat (uint cnt, SPEC&& delimDef)
{
return repeat (cnt,cnt, forward<SPEC> (delimDef));
}
template<typename SPEC>
auto
repeat (uint min, uint max, SPEC&& delimDef)
{
if (max<min)
throw err::Invalid{_Fmt{"Invalid repeated syntax-spec: min:%d > max:%d"}
% min % max };
if (max == 0)
throw err::Invalid{"Invalid repeat with max ≡ 0 repetitions"};
return accept(
repeatedConnex (min,max
,move(parse_)
,Parser{forward<SPEC> (delimDef)}));
}
private:
Eval<Result>& eval() { return *this;}
};
template<typename SPEC>
auto
accept (SPEC&& clauseDef)
@ -490,8 +571,9 @@ using Sigi = typename _Fun<PFun>::Sig;
return Syntax{Parser{forward<SPEC> (clauseDef)}};
}
// template<class PAR>
// Parser(Syntax<PAR> const&) -> Parser<typename PAR::Connex>;
/** empty syntax clause to start further definition */
auto accept() { return Syntax<Parser<NulP>>{}; }
}// namespace parse

View file

@ -20,7 +20,6 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/parse.hpp"
//#include "lib/iter-explorer.hpp"
//#include "lib/format-util.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/test/diagnostic-output.hpp"//////////////////TODO
@ -382,13 +381,13 @@ namespace test {
return hasResults()? IterEval{move(results), consumed}
: IterEval{std::nullopt};
};
string s1{"Seit umschlungen, Millionen"};
string s1{"seid umschlungen, Millionen"};
string s2{"beguile, extort, profit"};
auto e1 = parseSeq(s1);
CHECK (e1.result);
CHECK (e1.result->size() == 1);
CHECK (e1.result->at(0).str() == "Seit");
CHECK (e1.result->at(0).str() == "seid");
CHECK (e1.result->at(0).suffix() == " umschlungen, Millionen");
CHECK (e1.consumed == 4);
@ -406,7 +405,49 @@ namespace test {
//______________________________________________
// DSL parse clause builder: iterative sequence...
auto syntax1 = accept("brazen").alt("bragging");
auto syntax1 = accept(term).repeat(",");
// Perform the same parse as demonstrated above....
CHECK (not syntax1.hasResult());
syntax1.parse(s1);
CHECK (syntax1.success());
auto res1 = syntax1.getResult();
CHECK (res1.size() == 1);
CHECK (res1.get(0).str() == "seid");
syntax1.parse(s2);
CHECK (syntax1.success());
res1 = syntax1.getResult();
CHECK (res1.size() == 3);
CHECK (res1[0].str() == "beguile");
CHECK (res1[1].str() == "extort" );
CHECK (res1[2].str() == "profit" );
auto syntax2 = accept(term).repeat(1,2,",");
auto syntax3 = accept(term).repeat(4,",");
syntax2.parse(s2);
syntax3.parse(s2);
CHECK ( syntax2);
CHECK (not syntax3);
CHECK (syntax2.getResult().size() == 2);
CHECK (s2.substr(syntax2.consumed()) == ", profit");
auto sx = s2 + " , \tdump";
syntax3.parse(sx);
CHECK (syntax3);
CHECK (syntax3.getResult().size() == 4);
CHECK (syntax3.getResult()[0].str() == "beguile");
CHECK (syntax3.getResult()[1].str() == "extort" );
CHECK (syntax3.getResult()[2].str() == "profit" );
CHECK (syntax3.getResult()[3].str() == "dump" );
auto syntax4 = accept(term).repeat();
syntax4.parse(s1);
CHECK (syntax4.success());
CHECK (syntax4.getResult().size() == 2);
CHECK (syntax4.getResult()[0].str() == "seid");
CHECK (syntax4.getResult()[1].str() == "umschlungen" );
CHECK (s1.substr(syntax4.consumed()) == ", Millionen");
}
};

View file

@ -55197,7 +55197,18 @@
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1736719956201" ID="ID_866854488" MODIFIED="1736720063070" TEXT="iter(parser, ...)"/>
</node>
<node BACKGROUND_COLOR="#dcd8bb" CREATED="1737571008910" ID="ID_1051885182" MODIFIED="1737571674702" TEXT="umgekehrte Postfix-Notation">
<linktarget COLOR="#fef8c9" DESTINATION="ID_1051885182" ENDARROW="Default" ENDINCLINATION="483;279;" ID="Arrow_ID_1143426887" SOURCE="ID_1134276650" STARTARROW="None" STARTINCLINATION="460;21;"/>
<linktarget COLOR="#fef8c9" DESTINATION="ID_1051885182" ENDARROW="Default" ENDINCLINATION="483;279;" ID="Arrow_ID_1290165292" SOURCE="ID_543391021" STARTARROW="None" STARTINCLINATION="554;61;"/>
<icon BUILTIN="ksmiletris"/>
<node CREATED="1737571129595" ID="ID_1227830528" MODIFIED="1737571145596" TEXT="Posfix-Operator nimmt stets die ganze Syntax-Klausel"/>
<node CREATED="1737571146527" ID="ID_1480801160" MODIFIED="1737571157199" TEXT="man definiert also von innen nach au&#xdf;en"/>
<node CREATED="1737571212401" ID="ID_1700130675" MODIFIED="1737571228018" TEXT="wichtige Modifier">
<node CREATED="1736719956201" ID="ID_866854488" MODIFIED="1737571192783" TEXT="repeat(N, delim)"/>
<node CREATED="1737571233558" ID="ID_1190994671" MODIFIED="1737571238865" TEXT="optional()"/>
<node CREATED="1737571257818" ID="ID_779919773" MODIFIED="1737571292552" TEXT="bracket(spec)"/>
</node>
</node>
</node>
<node CREATED="1736724867345" ID="ID_1842306489" MODIFIED="1736724871350" TEXT="Model">
@ -55924,8 +55935,7 @@
&#10233; Resultat: man kann in den jeweiligen &#171;Slot&#187; nur mit einem kompatiblen Typ rein, und Typsicherheit ist gew&#228;hrleistet (im Parser; wenn ein Client falsch zugreift, ist er selber schuld)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<arrowlink COLOR="#36a9cb" DESTINATION="ID_767723954" ENDARROW="Default" ENDINCLINATION="1044;0;" ID="Arrow_ID_234371683" STARTARROW="None" STARTINCLINATION="257;10;"/>
<icon BUILTIN="button_ok"/>
</node>
@ -56533,7 +56543,7 @@
</node>
<node COLOR="#338800" CREATED="1737417129349" ID="ID_1317057698" MODIFIED="1737512033655" TEXT="Struktur f&#xfc;r den Kombinator darstellen">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1737482932204" ID="ID_543248475" MODIFIED="1737509621118" TEXT="Aufgabe: Branch-Models generieren">
<node COLOR="#338800" CREATED="1737482932204" FOLDED="true" ID="ID_543248475" MODIFIED="1737581176266" TEXT="Aufgabe: Branch-Models generieren">
<icon BUILTIN="button_ok"/>
<node CREATED="1737482977331" ID="ID_63052973" MODIFIED="1737483103594" TEXT="Analog zum SeqModel, aber...">
<richcontent TYPE="NOTE"><html>
@ -56553,8 +56563,7 @@
</li>
</ul>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1737482960340" ID="ID_835268271" MODIFIED="1737482976766" TEXT="Fallunterscheidung">
<node CREATED="1737483106692" ID="ID_483924984" MODIFIED="1737483124362" TEXT="linker Zweig: ein isolierter Einzel-Wert"/>
@ -56568,8 +56577,7 @@
linker Zweig: ein sub-Model, in dem <i>irgend ein Zweig</i>&#160;gematched hat
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1737483167585" ID="ID_185978077" MODIFIED="1737483181891" TEXT="rechter Zweig: (stets) ein isolierter Einzel-Wert"/>
<node CREATED="1737483184655" ID="ID_1855620876" MODIFIED="1737483198592" TEXT="weder-noch: leeres Resultat"/>
@ -56600,8 +56608,7 @@
Der Argument-Pack mu&#223; stets am Ende stehen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node COLOR="#435e98" CREATED="1737483893623" ID="ID_1013616792" MODIFIED="1737496418453" TEXT="L&#xf6;sung daf&#xfc;r aufbauen">
<icon BUILTIN="yes"/>
@ -56630,8 +56637,7 @@
Grundidee: man baut die neue, umgebaute Typ-Sequenz in den variadischen Argumenten <i>eines beliebigen Templates,</i>&#160;das selbst als Template-Template-Parameter gegeben wird. Damit kann man unmittelbar in einem einzigen Zug das redefinierte Ziel-Template konstruieren, ohne erst in eine andere Verarbeitungs-Dom&#228;ne (tuple, Typsequenz, Typliste) mappen zu m&#252;ssen. Zudem kann das gleiche Verarbeitungs-Template auch Spezial-Belegungen f&#252;r Hilfs-Operationen mit anbieten, und man kann gleich die h&#228;ufigsten verwandten Tools in einer einzigen Definition zur Verf&#252;gung stellen.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1737496129468" ID="ID_1009577491" MODIFIED="1737496733785" TEXT="kann diverse Rebind-Funktionen in ein einziges Hilfstemplate packen">
<arrowlink COLOR="#fdfcc6" DESTINATION="ID_1900356198" ENDARROW="Default" ENDINCLINATION="17;-73;" ID="Arrow_ID_987482225" STARTARROW="None" STARTINCLINATION="-279;12;"/>
@ -56653,8 +56659,7 @@
da zeichnet sich ein Schema ab, das die bekannten Sequenz-Umordnungen sehr direkt ausf&#252;hrt, ohne erst in eine andere Repr&#228;sentation (wie Typelist) zu mappen. Trotzdem ist der Aufwand O(n), f&#252;r das Umkehren der Sequenz sogar O(n&#178;)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1737496270577" ID="ID_368868253" MODIFIED="1737496282074" TEXT="nicht einmal Typelist">
<icon BUILTIN="idea"/>
</node>
@ -56674,7 +56679,7 @@
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1737503596247" ID="ID_371220796" MODIFIED="1737509623137" TEXT="Auswertung und Model-Erzeugung">
<node COLOR="#338800" CREATED="1737503596247" FOLDED="true" ID="ID_371220796" MODIFIED="1737581175044" TEXT="Auswertung und Model-Erzeugung">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1737503609673" ID="ID_984166098" MODIFIED="1737507882083" TEXT="wieder zun&#xe4;chst freistehend im Test ausformulieren">
<icon BUILTIN="button_ok"/>
@ -56692,8 +56697,7 @@
...Hinweis darauf ist der Umstand, da&#223; ich gar nicht mehr viel auswerten / pr&#252;fen mu&#223;, sondern direkt der Match auf die Konstruktor-Argumente den Rest der Logik erledigt.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737504141641" ID="ID_457554053" MODIFIED="1737507459721" TEXT="Problem: Konstruktor-Signaturen k&#xf6;nnen zusammenfallen">
@ -56716,8 +56720,7 @@
da geht n&#228;mlich eine Branch-ID ein, und die mu&#223; &lt;= TOP sein
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
</node>
@ -56735,8 +56738,9 @@
</node>
</node>
</node>
<node CREATED="1737513793917" ID="ID_295869669" MODIFIED="1737513801028" TEXT="Iterativ-Kombinator bauen">
<node CREATED="1737513809440" ID="ID_933768224" MODIFIED="1737557474045" TEXT="Ansatz">
<node COLOR="#338800" CREATED="1737513793917" ID="ID_295869669" MODIFIED="1737581158352" TEXT="Iterativ-Kombinator bauen">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1737513809440" ID="ID_933768224" MODIFIED="1737581154369" TEXT="Ansatz">
<icon BUILTIN="info"/>
<node CREATED="1737513818322" ID="ID_532960229" MODIFIED="1737513970917" TEXT="speziell gecodeter Seq-Kombinator"/>
<node CREATED="1737514200891" ID="ID_349069421" MODIFIED="1737514255695" TEXT="hat Backtracking zum Abbruch">
@ -56749,8 +56753,7 @@
wenn am Ende keine weitere Iteration akzeptiert werden kann, ist das kein Fehler, sondern wir stehen hinter der zuletzt akzeptierten Iteration
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1737514258866" ID="ID_1304545890" MODIFIED="1737514379504" TEXT="(optional) Trenner mit 1-Fall-Behandlung">
<richcontent TYPE="NOTE"><html>
@ -56762,8 +56765,7 @@
ein Trenner mu&#223; nicht gegeben sein (dann wird lediglich der Rumpf iteriert); wenn aber ein Trenner gegeben ist, dann wird er beim 1.Mal explizit &#252;bersprungen (darf also nicht da sein), bei allen anderen Iterationen wird er zu Beginn der Iteration erwartet
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1737514443537" ID="ID_1253748065" MODIFIED="1737514459585" TEXT="es ist eine Variante mit zwei Argumenten"/>
<node CREATED="1737514460215" ID="ID_58679545" MODIFIED="1737514470050" TEXT="das letzte Argument ist stets der Schleifenrumpf"/>
<node CREATED="1737514506380" ID="ID_1955741808" MODIFIED="1737514520395" TEXT="der Trenner hat keine Model-Ankn&#xfc;pfung">
@ -56780,8 +56782,7 @@
man kann sich Situationen denken.... aber dann h&#228;tte man auch stets dieses Ergebnis-Tupel zu handhaben.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
@ -56790,15 +56791,15 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1737514608995" ID="ID_1247344786" MODIFIED="1737514623977" TEXT="Zahl der Iterationen und Modell-Repr&#xe4;sentation?">
<node COLOR="#435e98" CREATED="1737514608995" ID="ID_1247344786" MODIFIED="1737581143659" TEXT="Zahl der Iterationen und Modell-Repr&#xe4;sentation?">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="help"/>
<node CREATED="1737514625345" ID="ID_417722298" MODIFIED="1737514657151" TEXT="Konsequenz: offen &#x27f9; kann kein Array sein"/>
<node CREATED="1737514768356" ID="ID_349567991" MODIFIED="1737514777505" TEXT="hier also dann doch noch Heap-Allokation">
<icon BUILTIN="smily_bad"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737514782252" ID="ID_611824133" MODIFIED="1737514853821" TEXT="Model-Variante f&#xfc;r feste Anzahl denkbar">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#5b280f" CREATED="1737514782252" ID="ID_611824133" MODIFIED="1737581139844" TEXT="Model-Variante f&#xfc;r feste Anzahl denkbar">
<icon BUILTIN="button_cancel"/>
<node CREATED="1737515006854" ID="ID_1604079761" MODIFIED="1737516214711" TEXT="feste Anzahl ist grunds&#xe4;tzlich notwendig">
<richcontent TYPE="NOTE"><html>
<head>
@ -56809,8 +56810,7 @@
weil wir bisher keinen generischen Rekursions-Mechanismus vorsehen und ansonsten die Zahl der Iterationen erst in einem Post-Proecssing-Schritt gepr&#252;ft werden k&#246;nnte.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1737516079454" ID="ID_1854925549" MODIFIED="1737516212509" TEXT="spezielles Modell erscheint mir unn&#xf6;tig komplex">
<richcontent TYPE="NOTE"><html>
@ -56822,8 +56822,7 @@
Es w&#252;rde sich um einige Randf&#228;lle handeln, denn im Regelfall ist eine Iteration offen / abz&#228;hlbar. Und wir m&#252;&#223;ten in eine derart performance-kritische Situation vorsto&#223;en, in der eine Heap-Allokation prohibitiv w&#228;re
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
@ -56840,9 +56839,9 @@
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737557808392" ID="ID_529869533" MODIFIED="1737557835573" TEXT="DSL-Varianten">
<icon BUILTIN="pencil"/>
<node COLOR="#435e98" CREATED="1737560210100" ID="ID_877662499" MODIFIED="1737560355110" TEXT="Einstieg top-level">
<node COLOR="#338800" CREATED="1737557808392" ID="ID_529869533" MODIFIED="1737581104395" TEXT="DSL-Varianten">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1737560210100" ID="ID_877662499" MODIFIED="1737569762631" TEXT="Spezifikations-Schema">
<icon BUILTIN="yes"/>
<node COLOR="#5b280f" CREATED="1737560240722" ID="ID_1633583353" MODIFIED="1737560259824" TEXT="eigentst&#xe4;ndige top-level syntax">
<icon BUILTIN="button_cancel"/>
@ -56854,10 +56853,42 @@
<node CREATED="1737560320472" ID="ID_89163254" MODIFIED="1737560334666" TEXT="viel lesbarer, da Syntax immer durch das Stichwort &quot;accept&quot; eingeleitet wird"/>
<node CREATED="1737560341821" ID="ID_713190827" MODIFIED="1737560350519" TEXT="spart eine Menge repetitive definitionen"/>
</node>
<node CREATED="1737569770813" ID="ID_858035606" MODIFIED="1737569832356" TEXT="noch besser: postfix repeat()">
<icon BUILTIN="yes"/>
<icon BUILTIN="yes"/>
<node CREATED="1737569852750" ID="ID_1574259355" MODIFIED="1737571535674" TEXT="Begr&#xfc;ndung: sonst bekommen wir stets eine implizite Sequenz mit Tupel auf Model-Ebene">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
dem inzwischen etablierten Schema der Syntax-Klauseln zufolge mu&#223; jeder Junktor etwas mit der aktuellen Syntax-Spec ankn&#252;pfen. Wenn nun ein iter()-Pr&#228;dikat essentiell eine neue Syntax anf&#228;ngt, w&#228;re eine implizite Konvention zu treffen, was mit der bestehenden Klausel passiert. Naheliegend w&#228;re eine Sequenz; dann besteht aber die Gefahr, da&#223; in der Praxis oft eine leere Sequenz spezifiziert wird (w&#228;re noch akzeptabel) &#8212; und man zur Model-Ankn&#252;pfung stets dieses Tupel aufmachen m&#252;&#223;te (schr&#246;cklich)
</p>
</body>
</html></richcontent>
<linktarget COLOR="#9091a5" DESTINATION="ID_1574259355" ENDARROW="Default" ENDINCLINATION="185;6;" ID="Arrow_ID_1603942836" SOURCE="ID_479972357" STARTARROW="None" STARTINCLINATION="128;-10;"/>
</node>
<node CREATED="1737557813571" ID="ID_337352454" MODIFIED="1737557821327" TEXT="mit Delimiter"/>
<node CREATED="1737557821953" ID="ID_874093473" MODIFIED="1737557826194" TEXT="ohne Delimiter"/>
<node CREATED="1737557826978" ID="ID_631895252" MODIFIED="1737557831945" TEXT="mit fester Anzahl"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1737570726608" ID="ID_1134276650" MODIFIED="1737571090798">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
dann mu&#223; man aber die <b>Postfix-takes-all-Logik</b>&#160;akzeptieren
</p>
</body>
</html></richcontent>
<arrowlink COLOR="#fef8c9" DESTINATION="ID_1051885182" ENDARROW="Default" ENDINCLINATION="483;279;" ID="Arrow_ID_1143426887" STARTARROW="None" STARTINCLINATION="460;21;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="forward"/>
</node>
</node>
</node>
<node COLOR="#435e98" CREATED="1737557813571" ID="ID_337352454" MODIFIED="1737581093314" TEXT="mit Delimiter"/>
<node COLOR="#435e98" CREATED="1737557821953" ID="ID_874093473" MODIFIED="1737581094904" TEXT="ohne Delimiter"/>
<node COLOR="#435e98" CREATED="1737557826978" ID="ID_631895252" MODIFIED="1737581097119" TEXT="mit fester Anzahl"/>
</node>
<node COLOR="#338800" CREATED="1737509793049" ID="ID_909696958" MODIFIED="1737557632090" TEXT="funktioniert im Test">
<arrowlink COLOR="#69a19e" DESTINATION="ID_1818283954" ENDARROW="Default" ENDINCLINATION="341;-27;" ID="Arrow_ID_1906636741" STARTARROW="None" STARTINCLINATION="-269;35;"/>
@ -56867,7 +56898,7 @@
<node CREATED="1737515386507" ID="ID_1671829221" MODIFIED="1737515396597" TEXT="optionaler Kombinator">
<node CREATED="1737515398692" ID="ID_1478704437" MODIFIED="1737515413091" TEXT="der ist einfach zu realisieren und sehr n&#xfc;tzlich"/>
<node CREATED="1737515413799" ID="ID_1235063232" MODIFIED="1737515424929" TEXT="das Model wird in einen std::optional gewickelt"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1737515765304" ID="ID_692646776" MODIFIED="1737515773735" TEXT="per postfix-Operator darstellbar?">
<node BACKGROUND_COLOR="#e5d4c6" COLOR="#435e98" CREATED="1737515765304" ID="ID_692646776" MODIFIED="1737571714725" TEXT="per postfix-Operator darstellbar?">
<icon BUILTIN="help"/>
<node CREATED="1737552397609" ID="ID_411565433" MODIFIED="1737552415673">
<richcontent TYPE="NODE"><html>
@ -56879,14 +56910,23 @@
der Implementierung nach <i>ist es</i>&#160;ein Dekorator
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1737552779748" ID="ID_1979253709" MODIFIED="1737552797867" TEXT="das Model wird in einen Optional gepackt"/>
<node CREATED="1737552798647" ID="ID_845579574" MODIFIED="1737552821888" TEXT="Scheitern des Parsers f&#xfc;hrt nur zu Backtracking"/>
</node>
<node CREATED="1737552824569" ID="ID_1896891774" MODIFIED="1737552864018" TEXT="zur Lesbarkeit beide DSL-Varianten bieten">
<node CREATED="1737552866525" ID="ID_849718453" MODIFIED="1737552892406" TEXT="Postfix geht immer wirkt aber auf die ganze Klausel"/>
<node CREATED="1737552896306" ID="ID_978425545" MODIFIED="1737552964929" TEXT="optional(parse) - Funktionsschreibweise bisweilsen klarer"/>
<node CREATED="1737552866525" ID="ID_849718453" MODIFIED="1737552892406" TEXT="Postfix geht immer wirkt aber auf die ganze Klausel">
<node CREATED="1737570726608" ID="ID_543391021" MODIFIED="1737571674702" TEXT="Postfix-takes-all-Logik">
<arrowlink COLOR="#fef8c9" DESTINATION="ID_1051885182" ENDARROW="Default" ENDINCLINATION="483;279;" ID="Arrow_ID_1290165292" STARTARROW="None" STARTINCLINATION="554;61;"/>
<font NAME="SansSerif" SIZE="12"/>
</node>
</node>
<node CREATED="1737552896306" ID="ID_978425545" MODIFIED="1737552964929" TEXT="optional(parse) - Funktionsschreibweise bisweilsen klarer">
<node CREATED="1737571480380" ID="ID_330911197" MODIFIED="1737571485431" TEXT="mu&#xdf; dann aber top-level sein"/>
<node CREATED="1737571488227" ID="ID_479972357" MODIFIED="1737571542441" TEXT="denn sonst widerspricht es der Syntax-Klausel-Logik">
<arrowlink COLOR="#9091a5" DESTINATION="ID_1574259355" ENDARROW="Default" ENDINCLINATION="185;6;" ID="Arrow_ID_1603942836" STARTARROW="None" STARTINCLINATION="128;-10;"/>
</node>
</node>
</node>
</node>
</node>
@ -56946,13 +56986,15 @@
</node>
<node COLOR="#435e98" CREATED="1737512403229" ID="ID_1723790713" MODIFIED="1737512410412" TEXT="Syntax erweitern"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737557499546" ID="ID_1714111876" MODIFIED="1737557636752" TEXT="Repetitiv-Kombinator">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1737557499546" ID="ID_1714111876" MODIFIED="1737581108530" TEXT="Repetitiv-Kombinator">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1737557515000" ID="ID_717799418" MODIFIED="1737557531293" TEXT="Parse-Mechanismus skizzieren"/>
<node COLOR="#435e98" CREATED="1737557534805" ID="ID_1997532643" MODIFIED="1737557551147" TEXT="Akzeptieren und Backtracking"/>
<node COLOR="#435e98" CREATED="1737509774878" ID="ID_1818283954" MODIFIED="1737557632090" TEXT="Kombinator per DSL">
<linktarget COLOR="#69a19e" DESTINATION="ID_1818283954" ENDARROW="Default" ENDINCLINATION="341;-27;" ID="Arrow_ID_1906636741" SOURCE="ID_909696958" STARTARROW="None" STARTINCLINATION="-269;35;"/>
</node>
<node COLOR="#435e98" CREATED="1737581111703" ID="ID_1277454723" MODIFIED="1737581129805" TEXT="mit vorgegebener Anzahl"/>
<node COLOR="#435e98" CREATED="1737581124685" ID="ID_196113271" MODIFIED="1737581129806" TEXT="ohne Delimiter"/>
</node>
</node>
</node>