Library: make bindMatch() more robust and enable structured bindings

...several improvements as result from the more elaborate test cases
 - spelling out the model types taken as argument can be challenging and tedious,
   thus improve the ability to pass a λ-generic.
 - furthermore, using structured bindings on a SeqModel can also simplifiy
   binding code; this did not work because the compiler picks the wrong strategy
   and attempts to bind the structure fields; need to provide explicit speicalisations
   to support the »tuple protocol« for SeqModel.

..considered several further helpers, (like auto-joining into a single string),
but in the end did not implement them, due to questionable relevance
This commit is contained in:
Fischlurch 2025-01-26 01:24:10 +01:00
parent b024b0baa6
commit 70a5a7a06c
4 changed files with 172 additions and 57 deletions

View file

@ -424,7 +424,7 @@ namespace std { // Specialisation to support C++ »Tuple Protocol« and structur
/** determine compile-time fixed size of a HeteroData */
template<typename...DATA>
struct tuple_size<lib::HeteroData<DATA...> >
: std::integral_constant<std::size_t, lib::HeteroData<DATA...>::size()>
: integral_constant<size_t, lib::HeteroData<DATA...>::size()>
{ };
/** expose the type of the I-th element of a HeteroData chain */
@ -447,13 +447,13 @@ namespace std { // Specialisation to support C++ »Tuple Protocol« and structur
/** determine compile-time fixed size of a StorageFrame */
template<size_t seg, typename...DATA>
struct tuple_size<lib::StorageFrame<seg,DATA...> >
: std::tuple_size<typename lib::StorageFrame<seg,DATA...>::Tuple>
: tuple_size<typename lib::StorageFrame<seg,DATA...>::Tuple>
{ };
/** delegate to the type access of a StorageFrame's underlying tuple */
template<size_t I, size_t seg, typename...DATA>
struct tuple_element<I, lib::StorageFrame<seg,DATA...> >
: std::tuple_element<I, typename lib::StorageFrame<seg,DATA...>::Tuple>
: tuple_element<I, typename lib::StorageFrame<seg,DATA...>::Tuple>
{ };
// no need to define an overload for std::get<i>

View file

@ -217,35 +217,26 @@ namespace util {
toStringConnex (CON&& connex, uint part)
{
using Result = typename CON::Result;
using Arg = std::add_rvalue_reference_t<Result>;
return Connex([baseConnex = forward<CON>(connex)
,part
]
(StrView toParse) -> Eval<string>
{
if constexpr (lib::meta::is_basically<Result,smatch>())
{
Eval<smatch> eval = baseConnex.parse (toParse);
if (eval.result)
auto eval = baseConnex.parse (toParse);
if (eval.result)
if constexpr (lib::meta::is_basically<Result,smatch>())
return {eval.result->str(part)
,eval.consumed
};
else
return {std::nullopt};
}
else
{ // defensive fall-back: ignore model, return accepted input part
size_t pre = leadingWhitespace (toParse);
return {string{toParse.substr (pre, eval.consumed)}
,eval.consumed
};
}
else
{
auto eval = baseConnex.parse (toParse);
if (eval.result)
{
size_t pre = leadingWhitespace (toParse);
return {string{toParse.substr (pre, eval.consumed)}
,eval.consumed
};
}
else
return {std::nullopt};
}
return {std::nullopt};
});
}
@ -294,7 +285,7 @@ namespace util {
: lib::BranchCase<CASES...>
{
using Alt = lib::BranchCase<CASES...>;
static constexpr size_t N = Alt::TOP;
static constexpr size_t N = sizeof...(CASES);
template<typename EXTRA>
using Additionally = AltModel<CASES...,EXTRA>;
@ -1059,4 +1050,20 @@ namespace util {
using parse::accept_repeated;
}// namespace util
namespace std { // Specialisation to support C++ »Tuple Protocol« and structured bindings.
/** determine compile-time fixed size of a SeqModel */
template<typename...ELMS>
struct tuple_size<util::parse::SeqModel<ELMS...> >
: tuple_size<typename util::parse::SeqModel<ELMS...>::Tup >
{ };
/** type of the I-th element of a SeqModel -> based on tuple type */
template<size_t I, typename...ELMS>
struct tuple_element<I, util::parse::SeqModel<ELMS...> >
: tuple_element<I, typename util::parse::SeqModel<ELMS...>::Tup >
{ };
}
#endif/*LIB_PARSE_H*/

View file

@ -333,7 +333,7 @@ namespace test {
CHECK (not syntax2.success());
syntax2.parse(s2);
CHECK (syntax2.success());
CHECK (syntax2.getResult().N == 2); // Note: further branch has been folded into an extended AltModel
CHECK (syntax2.getResult().N == 3); // Note: further branch has been folded into an extended AltModel
CHECK (syntax2.getResult().selected() == 0); // ... string s2 still matched the same branch (#0)
CHECK (syntax2.getResult().get<0>().str() == "brazen");
@ -500,7 +500,7 @@ namespace test {
Model res2 = syntax.getResult();
CHECK (typeSymbol(res2) == "SeqModel"); // Syntax SeqModel
CHECK (typeSymbol(res2.get<0>()) == "IterModel"); // repeat(word) opt IterModel optional
CHECK (typeSymbol(res2.get<1>()) == "optional"); // | |
CHECK (typeSymbol(res2.get<1>()) == "optional"); // | |
CHECK (typeSymbol(*res2.get<1>()) == "SeqModel"); // Syntax SeqModel
CHECK (typeSymbol(res2.get<1>()->get<0>()) == "match_results"); // "and" repeat(word) Terminal IterModel
CHECK (typeSymbol(res2.get<1>()->get<1>()) == "IterModel"); //
@ -564,7 +564,9 @@ namespace test {
/** @test define syntax with bracketed sub-expressions */
/** @test attach model-transformation functions at various levels,
* which is the primary intended way to build results from the parse.
*/
void
verify_modelBinding()
{
@ -599,10 +601,20 @@ namespace test {
CHECK (syntax1c.parse("ham actor").getResult() == "ham-actor");
CHECK (syntax1c.parse("con artist").getResult() == "con-artist");
auto syntax1d =accept(word).seq(word)
auto syntax1d = accept(word).seq(word)
.bindMatch(); // generic shortcut: ignore model, yield accepted part of input
CHECK (syntax1d.parse("ham actor").getResult() == "ham actor");
CHECK (syntax1d.parse(" ham actor").getResult() == "ham actor");
// another example to demonstrate arbitrary transformations:
// each sub-expr counts the letters, and the top-level binding sums those up
auto letterCnt = accept(word).bindMatch().bind([](string s){ return s.size(); });
auto syntax1e = accept(letterCnt)
.seq(letterCnt)
.bind([](auto m){ auto [l1,l2] = m; return l1+l2; });
// note this time we provide a λ-generic and use a structured binding
CHECK (syntax1e.parse("ham actor").getResult() == 8);
CHECK (syntax1e.parse("con artist").getResult() == 9);
}
};

View file

@ -57017,9 +57017,9 @@
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737762868854" ID="ID_311219420" MODIFIED="1737762954045" TEXT="Result-Bindings">
<linktarget COLOR="#fadad2" DESTINATION="ID_311219420" ENDARROW="Default" ENDINCLINATION="-362;51;" ID="Arrow_ID_1251442496" SOURCE="ID_1290815698" STARTARROW="None" STARTINCLINATION="-954;49;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1737762868854" ID="ID_311219420" MODIFIED="1737850558883" TEXT="Result-Bindings">
<linktarget COLOR="#d2fad9" DESTINATION="ID_311219420" ENDARROW="Default" ENDINCLINATION="-362;51;" ID="Arrow_ID_1251442496" SOURCE="ID_1290815698" STARTARROW="None" STARTINCLINATION="-954;49;"/>
<icon BUILTIN="button_ok"/>
<node CREATED="1737762977024" ID="ID_1561603785" MODIFIED="1737762981006" TEXT="Basis-Implementierung">
<node CREATED="1737762981897" ID="ID_1090727371" MODIFIED="1737763001027" TEXT="ist schon da">
<richcontent TYPE="NOTE"><html>
@ -57037,8 +57037,8 @@
</node>
<node CREATED="1737763004632" ID="ID_822193320" MODIFIED="1737763015437" TEXT="ist nur ein Dekorator der Parse-Funktion"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737763021537" ID="ID_1389624027" MODIFIED="1737768628999" TEXT="DSL-Einbindung">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1737763021537" ID="ID_1389624027" MODIFIED="1737849871467" TEXT="DSL-Einbindung">
<icon BUILTIN="button_ok"/>
<node CREATED="1737763027300" ID="ID_681702080" MODIFIED="1737763052404">
<richcontent TYPE="NODE"><html>
<head>
@ -57053,7 +57053,7 @@
</richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1737763069414" ID="ID_1049523751" MODIFIED="1737763109434">
<node COLOR="#435e98" CREATED="1737763069414" ID="ID_1049523751" MODIFIED="1737849866205">
<richcontent TYPE="NODE"><html>
<head>
@ -57103,7 +57103,7 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737763306315" ID="ID_556563323" MODIFIED="1737776731540">
<node COLOR="#435e98" CREATED="1737763306315" ID="ID_556563323" MODIFIED="1737849862021">
<richcontent TYPE="NODE"><html>
<head>
@ -57115,9 +57115,8 @@
</body>
</html>
</richcontent>
<icon BUILTIN="pencil"/>
<node CREATED="1737817661406" ID="ID_74788283" MODIFIED="1737817685150" TEXT="auf Matcher &#x27fc; match-group"/>
<node CREATED="1737817685762" ID="ID_522207502" MODIFIED="1737817743080" TEXT="auf compound-Model &#x27fc; Teilkomponente">
<node CREATED="1737817685762" ID="ID_522207502" MODIFIED="1737844301800" TEXT="eine Verallgemeinerung versuchen">
<node CREATED="1737818008232" ID="ID_1008681073" MODIFIED="1737818043982" TEXT="mu&#xdf; daf&#xfc;r constexpr-branch mit switch-on-Type machen"/>
<node COLOR="#5b280f" CREATED="1737818191905" ID="ID_253639135" MODIFIED="1737818824310" TEXT="diese Verzweigung in der Builder-Methode machen">
<richcontent TYPE="NOTE"><html>
@ -57143,8 +57142,8 @@
<linktarget COLOR="#d21839" DESTINATION="ID_580741187" ENDARROW="Default" ENDINCLINATION="-152;6;" ID="Arrow_ID_1339747714" SOURCE="ID_1259641042" STARTARROW="None" STARTINCLINATION="21;-32;"/>
<icon BUILTIN="clanbomber"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737818936319" ID="ID_1719662007" MODIFIED="1737820213249" TEXT="mu&#xdf; also speziellen Connex erzeugen">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1737818936319" ID="ID_1719662007" MODIFIED="1737845413910" TEXT="mu&#xdf; also speziellen Connex erzeugen">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1737819592756" ID="ID_634105899" MODIFIED="1737820210832" TEXT="dann auch besser als toStringConnex ">
<richcontent TYPE="NOTE"><html>
<head>
@ -57161,13 +57160,22 @@
<node COLOR="#338800" CREATED="1737820217112" ID="ID_983053078" MODIFIED="1737820261322" TEXT="da kommt dann die constexpr-if-Kaskade rein">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1737820230519" ID="ID_4755618" MODIFIED="1737820256010" TEXT="repetitiever Code &#x27f9; vereinfachen">
<icon BUILTIN="flag-pink"/>
<node COLOR="#435e98" CREATED="1737820230519" ID="ID_4755618" MODIFIED="1737845408706" TEXT="repetitiever Code &#x27f9; vereinfachen">
<node CREATED="1737844669441" ID="ID_82924290" MODIFIED="1737844753235" TEXT="jetzt viel einfacher...">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
nachdem ich die Model-F&#228;lle wegdiskutiert habe &#9786;
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737820266129" ID="ID_1685629820" MODIFIED="1737820275519" TEXT="brauche Traits zum Erkennen der Modell-F&#xe4;lle">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1737820277891" ID="ID_1704538350" MODIFIED="1737820288067" TEXT="Problem: es sind variadic-templates">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1737844971662" ID="ID_48221377" MODIFIED="1737844986417" TEXT="die constexpr-if kann nach innen!">
<icon BUILTIN="idea"/>
</node>
</node>
</node>
@ -57177,19 +57185,88 @@
<node CREATED="1737818264773" ID="ID_120023356" MODIFIED="1737818272264" TEXT="genereller fall-Back"/>
<node CREATED="1737818273492" ID="ID_1978233039" MODIFIED="1737818392552" TEXT="damit fehlertolerant"/>
</node>
<node COLOR="#5b280f" CREATED="1737844303914" ID="ID_533069226" MODIFIED="1737844325844" TEXT="auf compound-Model &#x27fc; Teilkomponente">
<icon BUILTIN="button_cancel"/>
<node CREATED="1737844326911" ID="ID_276945387" MODIFIED="1737844341721" TEXT="wird sehr komplex umzusetzen"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737820277891" ID="ID_1885712747" MODIFIED="1737844365946" TEXT="Problem: es sind variadic-templates">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737820266129" ID="ID_1586481229" MODIFIED="1737844365946" TEXT="brauche Traits zum Erkennen der Modell-F&#xe4;lle">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1737844371498" ID="ID_641248746" MODIFIED="1737844388561" TEXT="man m&#xfc;&#xdf;te mit allen misch-F&#xe4;llen umgehen k&#xf6;nnen"/>
<node CREATED="1737844390141" ID="ID_730168468" MODIFIED="1737844538602" TEXT="und was dann machen....?">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
es br&#228;uchte f&#252;r alle erdenklichen F&#228;lle einen Pfad, um auf einen String zu kommen; also br&#228;uchte es sowas wie einen operator string(), oder man m&#252;&#223;te rekursiv in alle Teilkomponenten hinein mappen; und was dann mit Komponenten, die bereits explizit transformiert wurden, wie erkennt man die, und was macht man mit denen??
</p>
</body>
</html>
</richcontent>
</node>
<node COLOR="#5b280f" CREATED="1737844404123" ID="ID_1490711015" MODIFIED="1737844630457" TEXT="Nutzen zweifelhaft">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
wozu will man das? doch nur f&#252;r Tests.
</p>
<p>
F&#252;r eine reale Anwendung sollte man m&#246;glichst tief unten mappen, und b&#228;uchte auch ein Konzept, um auf einen gemeinsamen Ergebnis-Typ zu kommen, m&#246;glicherweise dann doch so etwas wie einen AST. <i>Und wenn man es dann doch wirklich br&#228;uchte, kann man's immer noch nachr&#252;sten</i>
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737509793049" ID="ID_1532451583" MODIFIED="1737763426814" TEXT="komplexere F&#xe4;lle testen">
</node>
</node>
<node COLOR="#338800" CREATED="1737509793049" ID="ID_1532451583" MODIFIED="1737850552941" TEXT="komplexere F&#xe4;lle testen">
<arrowlink COLOR="#69a19e" DESTINATION="ID_1875116599" ENDARROW="Default" ENDINCLINATION="365;-30;" ID="Arrow_ID_1373514851" STARTARROW="None" STARTINCLINATION="-268;27;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1737768590998" ID="ID_1409763179" MODIFIED="1737768617430" TEXT="einfache F&#xe4;lle funktionieren mal grunds&#xe4;tzlich wie erwartet">
<icon BUILTIN="ksmiletris"/>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1737768366091" ID="ID_1745696338" MODIFIED="1737768442619" TEXT="bind-Functions schreiben ist m&#xfc;hsam">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737768366091" ID="ID_1745696338" MODIFIED="1737849847981" TEXT="bind-Functions schreiben ist m&#xfc;hsam">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1737768409191" ID="ID_46123353" MODIFIED="1737768426237" TEXT="&#x3bb;-generic funktionieren nicht wie gew&#xfc;nscht"/>
<node CREATED="1737768409191" ID="ID_46123353" MODIFIED="1737768426237" TEXT="&#x3bb;-generic funktionieren nicht wie gew&#xfc;nscht">
<node COLOR="#435e98" CREATED="1737843913515" ID="ID_561991367" MODIFIED="1737849603837" TEXT="Typ-detection nachsch&#xe4;rfen"/>
<node COLOR="#5b280f" CREATED="1737843926181" ID="ID_339480113" MODIFIED="1737849630922" TEXT="besser auf fried-Function get&lt;i&gt;(model) setzen">
<icon BUILTIN="button_cancel"/>
<node CREATED="1737849632673" ID="ID_968615561" MODIFIED="1737849639804" TEXT="std::get funktioniert bereits"/>
</node>
<node COLOR="#435e98" CREATED="1737843950560" ID="ID_77042913" MODIFIED="1737849817609" TEXT="kl&#xe4;ren warum structured Bindings nicht funktionieren">
<node CREATED="1737849641960" ID="ID_510578678" MODIFIED="1737849815956" TEXT="Grund: std::tuple_size nicht spezialisiert &#x27f9; biegt in Struct-Binding ab">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Die C++ &#187;structured bindings&#171; funktionieren f&#252;r Arrays, f&#252;r <i>tuple-like</i>&#160; und aber auch f&#252;r einfache PODs. Wenn std::tuple_size ein <i>incomplete-type</i>&#160; ist, dann versucht der Compiler ein Binding auf Struct-Felder, scheitert aber daran, da&#223; es eine nicht-triviale Basis-Klasse gibt (und damit die Feld-Nummer nicht mehr offensichtlich klar ist)
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
</node>
<node COLOR="#338800" CREATED="1737849793598" ID="ID_213117529" MODIFIED="1737849811165" TEXT="also die beiden notwendigen Spezialisierungen in den namespace std;">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node CREATED="1737768426892" ID="ID_1722753025" MODIFIED="1737768440774" TEXT="und sonst mu&#xdf; man immer die Model-Namen ganz anschreiben"/>
<node CREATED="1737817647567" ID="ID_1641437634" MODIFIED="1737817658826" TEXT="bindMatch() k&#xf6;nnte noch mehr tun"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1737849826967" ID="ID_1650492122" MODIFIED="1737849845902" TEXT="erst mal weiter sehen wie sehr das in der Praxis hindert">
<icon BUILTIN="hourglass"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1737776743702" ID="ID_1501521982" MODIFIED="1737817618502" TEXT="sonderbares Verhalten mit zwe sub-Syntax-Klauseln und Binder">
<icon BUILTIN="broken-line"/>
@ -57219,9 +57296,16 @@
</richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1737850519594" ID="ID_1668182663" MODIFIED="1737850539048" TEXT="auch mit &#x3bb;-generic binden">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1737850539991" ID="ID_841296051" MODIFIED="1737850551486" TEXT="komplexe Transformation in was anderes als string">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1737515362910" ID="ID_1587990202" MODIFIED="1737693815237" TEXT="offene Rekursion">
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1737515362910" ID="ID_1587990202" MODIFIED="1737850611368" TEXT="offene Rekursion">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1737515599278" ID="ID_1897353084" MODIFIED="1737515606925" TEXT="schwierige Frage....">
<icon BUILTIN="help"/>
<node CREATED="1737515610957" ID="ID_1394504016" MODIFIED="1737515628606" TEXT="es ist nat&#xfc;rlich ein Kern-Feature von recursive-descent"/>
@ -57367,7 +57451,7 @@
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#e8d8bb" CREATED="1737757274593" ID="ID_1290815698" MODIFIED="1737762963804" TEXT="User mu&#xdf; typischerweise ein Result-Binding definieren">
<node BACKGROUND_COLOR="#e8d8bb" CREATED="1737757274593" ID="ID_1290815698" MODIFIED="1737850572394" TEXT="User mu&#xdf; typischerweise ein Result-Binding definieren">
<richcontent TYPE="NOTE"><html>
<head>
@ -57379,7 +57463,7 @@
</body>
</html>
</richcontent>
<arrowlink COLOR="#fadad2" DESTINATION="ID_311219420" ENDARROW="Default" ENDINCLINATION="-362;51;" ID="Arrow_ID_1251442496" STARTARROW="None" STARTINCLINATION="-954;49;"/>
<arrowlink COLOR="#d2fad9" DESTINATION="ID_311219420" ENDARROW="Default" ENDINCLINATION="-362;51;" ID="Arrow_ID_1251442496" STARTARROW="None" STARTINCLINATION="-954;49;"/>
<icon BUILTIN="forward"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1737762884132" HGAP="23" ID="ID_1097242773" MODIFIED="1737762918245" TEXT="&#x27f9; das mu&#xdf; das n&#xe4;chste Thema sein" VSHIFT="10">
<font NAME="SansSerif" SIZE="10"/>
@ -57611,13 +57695,25 @@
<node COLOR="#435e98" CREATED="1737692995551" ID="ID_1734452138" MODIFIED="1737693020069" TEXT="Backtracking &#xfc;ber Whitespace bei optionaler Klammer"/>
<node COLOR="#435e98" CREATED="1737693009389" ID="ID_1022057324" MODIFIED="1737693020069" TEXT="beliebige Ausdr&#xfc;cke zur Klammerung"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737763262674" ID="ID_1514969475" MODIFIED="1737763269614" TEXT="Model-Bindings">
<icon BUILTIN="pencil"/>
<node CREATED="1737763440641" ID="ID_1186409722" MODIFIED="1737763479551" TEXT="einfache Transformatinon demonstrieren"/>
<node CREATED="1737763449624" ID="ID_299994031" MODIFIED="1737763466753" TEXT="bindMatch testen, auch mit Sub-Matches"/>
<node CREATED="1737509774878" ID="ID_1875116599" MODIFIED="1737763432229" TEXT="komplexe mehrstufige Transformation">
<node COLOR="#338800" CREATED="1737763262674" ID="ID_1514969475" MODIFIED="1737850599611" TEXT="Model-Bindings">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1737763440641" ID="ID_1186409722" MODIFIED="1737850581946" TEXT="einfache Transformatinon demonstrieren"/>
<node COLOR="#435e98" CREATED="1737763449624" ID="ID_299994031" MODIFIED="1737850584818" TEXT="bindMatch testen, auch mit Sub-Matches"/>
<node COLOR="#435e98" CREATED="1737509774878" ID="ID_1875116599" MODIFIED="1737850586473" TEXT="komplexe mehrstufige Transformation">
<linktarget COLOR="#69a19e" DESTINATION="ID_1875116599" ENDARROW="Default" ENDINCLINATION="365;-30;" ID="Arrow_ID_1373514851" SOURCE="ID_1532451583" STARTARROW="None" STARTINCLINATION="-268;27;"/>
</node>
<node COLOR="#435e98" CREATED="1737850587657" ID="ID_1051789530" MODIFIED="1737850597849" TEXT="was anderes als strings erzeugen"/>
</node>
<node CREATED="1737845308863" ID="ID_383219766" MODIFIED="1737845313627" TEXT="simpleUsage">
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1737845314577" ID="ID_453689160" MODIFIED="1737845324102" TEXT="puh ... was zeigen wir da?">
<icon BUILTIN="help"/>
<node CREATED="1737845330906" ID="ID_775079358" MODIFIED="1737845372016" TEXT="nicht zu komplex machen">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1737845346563" ID="ID_1149093005" MODIFIED="1737845367680" TEXT="aber etwas, das man nicht mit RegExp parsen k&#xf6;nnte">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>