Library: further work out the framework for TextTemplate instantiation
This commit is contained in:
parent
d2dcf6c163
commit
7893cc99c3
2 changed files with 261 additions and 40 deletions
|
|
@ -23,7 +23,69 @@
|
|||
|
||||
/** @file text-template.hpp
|
||||
** A minimalistic text templating engine with flexible data binding.
|
||||
** Text template instantiation implies the interpretation of a template specification,
|
||||
** which contains literal text with some placeholder tags. This is combined with an actual
|
||||
** data source; the engine needs to retrieve data values as directed by key names extracted
|
||||
** from the placeholders and render and splice them into the placeholder locations. This
|
||||
** process is crucial for code generation, for external tool integration and is also often
|
||||
** used for dynamic web page generation. Several external libraries are available, offering
|
||||
** a host of extended functionality. This library implementation for internal use by the
|
||||
** Lumiera application however attempts to remain focused on the essential functionality,
|
||||
** with only minimal assumptions regarding the data source used for instantiation. Rather
|
||||
** than requiring data to be given in some map, or custom JSON data type, or some special
|
||||
** property-tree or dynamic object type, a _data binding protocol_ is stipulated; this
|
||||
** way, any data type can be attached, given that five generic functions can be implemented
|
||||
** to establish the binding. By default, a pre-defined binding is provided for a STL map
|
||||
** and for Lumiera's »External Tree Description« format based on `Record<GenNode>`.
|
||||
**
|
||||
** # Template syntax and features
|
||||
**
|
||||
** TextTemplate is able to substitute simple placeholders by name, it can handle
|
||||
** conditional sections and supports a data iteration construct for a nested scope.
|
||||
** The supported functionality is best explained with an example:
|
||||
** \code
|
||||
** Rendered at ${date}.
|
||||
** ${if critical}
|
||||
** WARNING: critical!
|
||||
** ${else}(routine report)${end if critical}
|
||||
**
|
||||
** Participants
|
||||
** ${for person}- ${name} ${if role}(${role})${end if role}
|
||||
** ${else}** no participants **
|
||||
** ${end for person}
|
||||
** \endcode
|
||||
** This template spec is parsed and preprocessed into an internal representation,
|
||||
** which can then be rendered with any suitable data source.
|
||||
** - the placeholder `${date}` is replaced by a value retrieved with the key "date"
|
||||
** - the conditional section will appear only if a key "critical" is defined
|
||||
** - when the data defines content under the key "person", and this content
|
||||
** can be suitably interpreted as a sequence of sub-scopes, then the »for block«
|
||||
** is instantiated for each entry, using the values retrieved through the keys
|
||||
** "name" and "role". Typically these keys are defined for each sub-scope
|
||||
** - note that the key "role" is enclosed into a conditional section
|
||||
** - note that both for conditional sections, and for iteration, an _else branch_
|
||||
** can be defined.
|
||||
** How data is actually accessed, and what constitutes a nested scope is obviously
|
||||
** a matter of the actual data binding, which is picked up through a template
|
||||
** specialisation for lib::TextTemplate::DataSource
|
||||
**
|
||||
** # Implementation notes
|
||||
**
|
||||
** The template specification is parsed and compiled immediately when constructing
|
||||
** the TextTemplate instance. At this point, syntactical errors, e.g. mismatched
|
||||
** conditional opening and closing tags will be detected and raised as exceptions.
|
||||
** The _compiled template_ is represented as a vector of action tokens, holding the
|
||||
** constant parts as strings in heap memory and marking the positions of placeholders
|
||||
** and block bounds.
|
||||
**
|
||||
** The actual instantiation is initiated through TextTemplate::render(), which picks
|
||||
** a suitable data binding (causing a compilation failure in case not binding can
|
||||
** be established). This function yields an iterator, which will traverse the
|
||||
** sequence of action tokens precompiled for this template and combine them
|
||||
** with the retrieved data, yielding a std::string_view for each instantiated
|
||||
** chunk of the template. The full result can thus be generated either by
|
||||
** looping, or by invoking util::join() on the provided iterator.
|
||||
**
|
||||
** @todo WIP-WIP-WIP 3/2024
|
||||
** @see TextTemplate_test
|
||||
** @see gnuplot-gen.hpp
|
||||
|
|
@ -43,26 +105,28 @@
|
|||
|
||||
//#include <cmath>
|
||||
//#include <limits>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
//#include <stdint.h>
|
||||
//#include <boost/rational.hpp>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
||||
// using Rat = boost::rational<int64_t>;
|
||||
// using boost::rational_cast;
|
||||
// using std::abs;
|
||||
using std::string;
|
||||
using StrView = std::string_view;
|
||||
|
||||
|
||||
namespace {// preconfigured TextTemplate data bindings
|
||||
namespace {
|
||||
|
||||
/** shorthand for an »iter-explorer« build from some source X */
|
||||
template<class X>
|
||||
using ExploreIter = decltype (lib::explore (std::declval<X>()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
/*****************************************//**
|
||||
* Text template substitution engine
|
||||
*/
|
||||
class TextTemplate
|
||||
|
|
@ -92,31 +156,48 @@ namespace lib {
|
|||
Idx refIDX{0};
|
||||
|
||||
template<class IT>
|
||||
string instantiate (IT&);
|
||||
};
|
||||
|
||||
/** Binding to a specific data source.
|
||||
* @note requires partial specialisation */
|
||||
template<class DAT, typename SEL=void>
|
||||
struct InstanceCore
|
||||
{
|
||||
static_assert (not sizeof(DAT),
|
||||
"unable to bind this data source "
|
||||
"for TextTemplate instantiation");
|
||||
StrView instantiate (IT&);
|
||||
};
|
||||
|
||||
/** the text template is compiled into a sequence of Actions */
|
||||
using ActionSeq = std::vector<Action>;
|
||||
|
||||
using PipeTODO = std::vector<string>;
|
||||
using InstanceIter = decltype (explore (std::declval<PipeTODO const&>()));
|
||||
|
||||
/** Binding to a specific data source.
|
||||
* @note requires partial specialisation */
|
||||
template<class DAT, typename SEL=void>
|
||||
class DataSource;
|
||||
|
||||
template<class SRC>
|
||||
class InstanceCore
|
||||
{
|
||||
using ActionIter = ExploreIter<ActionSeq const&>;
|
||||
using DataCtxIter = typename SRC::Iter;
|
||||
using NestedCtx = std::pair<DataCtxIter, SRC>;
|
||||
using CtxStack = std::stack<NestedCtx, std::vector<NestedCtx>>;
|
||||
|
||||
SRC dataSrc_;
|
||||
ActionIter actionIter_;
|
||||
CtxStack ctxStack_;
|
||||
StrView rendered_;
|
||||
|
||||
public:
|
||||
InstanceCore (ActionSeq const& actions, SRC);
|
||||
|
||||
bool checkPoint() const;
|
||||
StrView& yield() const;
|
||||
void iterNext();
|
||||
};
|
||||
|
||||
template<class DAT>
|
||||
using InstanceIter = ExploreIter<InstanceCore<DataSource<DAT>>>;
|
||||
|
||||
public:
|
||||
TextTemplate(string spec)
|
||||
{ }
|
||||
|
||||
template<class DAT>
|
||||
InstanceIter
|
||||
InstanceIter<DAT>
|
||||
render (DAT const& data) const;
|
||||
|
||||
template<class DAT>
|
||||
|
|
@ -126,9 +207,75 @@ namespace lib {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ======= preconfigured data bindings ======= */
|
||||
|
||||
template<class DAT, typename SEL=void>
|
||||
struct TextTemplate::DataSource
|
||||
{
|
||||
static_assert (not sizeof(DAT),
|
||||
"unable to bind this data source "
|
||||
"for TextTemplate instantiation");
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TextTemplate::DataSource<std::map<string,string>>
|
||||
{
|
||||
using Iter = std::string_view;
|
||||
};
|
||||
|
||||
|
||||
template<class SRC>
|
||||
TextTemplate::InstanceCore<SRC>::InstanceCore (TextTemplate::ActionSeq const& actions, SRC s)
|
||||
: dataSrc_{s}
|
||||
, actionIter_{explore (actions)}
|
||||
, ctxStack_{}
|
||||
{ }
|
||||
|
||||
|
||||
template<class SRC>
|
||||
inline bool
|
||||
TextTemplate::InstanceCore<SRC>::checkPoint() const
|
||||
{
|
||||
UNIMPLEMENTED ("TextTemplate instantiation: check point on action token");
|
||||
}
|
||||
|
||||
template<class SRC>
|
||||
inline StrView&
|
||||
TextTemplate::InstanceCore<SRC>::yield() const
|
||||
{
|
||||
UNIMPLEMENTED ("TextTemplate instantiation: yield instantiated string element for action token");
|
||||
}
|
||||
|
||||
template<class SRC>
|
||||
inline void
|
||||
TextTemplate::InstanceCore<SRC>::iterNext()
|
||||
{
|
||||
UNIMPLEMENTED ("TextTemplate instantiation: advance to interpretation of next action token");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interpret an action token from the compiled text template
|
||||
* based on the given data binding and iteration state to yield a rendering
|
||||
* @param instanceIter the wrapped InstanceCore with the actual data binding
|
||||
* @return a string-view pointing to the effective rendered chunk corresponding to this action
|
||||
*/
|
||||
template<class IT>
|
||||
inline StrView
|
||||
TextTemplate::Action::instantiate (IT& instanceIter)
|
||||
{
|
||||
UNIMPLEMENTED ("actual implementation of template action interpretation");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** */
|
||||
template<class DAT>
|
||||
inline TextTemplate::InstanceIter
|
||||
inline TextTemplate::InstanceIter<DAT>
|
||||
TextTemplate::render (DAT const& data) const
|
||||
{
|
||||
UNIMPLEMENTED ("actually instantiate the text template");
|
||||
|
|
|
|||
|
|
@ -112529,12 +112529,13 @@ std::cout << tmpl.render({"what", "World"}) << s
|
|||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1710802871952" ID="ID_1230958115" MODIFIED="1710802881229" TEXT="benötigte Operationen">
|
||||
<icon BUILTIN="info"/>
|
||||
<node CREATED="1710802887262" ID="ID_943892158" MODIFIED="1710803289340" TEXT="DataSrc.retrieveContent(key) ⟼ iter"/>
|
||||
<node CREATED="1710802982433" ID="ID_555113619" MODIFIED="1710803294652" TEXT="DataSrc.handleMiss(key) ⟼ iter">
|
||||
<node CREATED="1710887924376" ID="ID_1738189195" MODIFIED="1710887947623" TEXT="DataSrc.contains(key) ⟼ bool"/>
|
||||
<node CREATED="1710802887262" ID="ID_943892158" MODIFIED="1710887952504" TEXT="DataSrc.retrieveContent(key) ⟼ string"/>
|
||||
<node CREATED="1710802982433" ID="ID_555113619" MODIFIED="1710887958495" TEXT="DataSrc.handleMiss(key) ⟼ string">
|
||||
<node CREATED="1710803102126" ID="ID_929049801" MODIFIED="1710803116035" TEXT="liefert einen Ersatz-Content"/>
|
||||
<node CREATED="1710803122407" ID="ID_1916953854" MODIFIED="1710803131553" TEXT="darf Exception werfen"/>
|
||||
</node>
|
||||
<node CREATED="1710803055072" ID="ID_1341021229" MODIFIED="1710803301854" TEXT="DataSrc.getSequence(iter) ⟼ iter">
|
||||
<node CREATED="1710803055072" ID="ID_1341021229" MODIFIED="1710888017135" TEXT="DataSrc.getSequence(key) ⟼ iter">
|
||||
<node CREATED="1710803141876" ID="ID_196999296" MODIFIED="1710803152399" TEXT="interpretiert Content in eine Datensequenz"/>
|
||||
<node CREATED="1710803153298" ID="ID_1252110387" MODIFIED="1710803171163" TEXT="liefert neuen Iterator über Sequenz-content"/>
|
||||
</node>
|
||||
|
|
@ -112549,16 +112550,45 @@ std::cout << tmpl.render({"what", "World"}) << s
|
|||
<node CREATED="1710803524513" ID="ID_527165239" MODIFIED="1710803549685" TEXT="ein generischer Datentyp (eigentlich das Binding)"/>
|
||||
<node CREATED="1710803532568" ID="ID_362764880" MODIFIED="1710803540795" TEXT="stellt die o.g. Operationen bereit"/>
|
||||
<node CREATED="1710803559841" ID="ID_978322266" MODIFIED="1710803571734" TEXT="kann ausgewertet werden um Dateninhalte zu gewinnen"/>
|
||||
<node CREATED="1710888899301" ID="ID_1431488282" MODIFIED="1710889348598" TEXT="muß zuweisbar sein (also letztlich ein Pointer auf die Daten)"/>
|
||||
<node CREATED="1710889358377" ID="ID_903149258" MODIFIED="1710889479699" TEXT="wird rekursiv / re-entrant verwendet">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das bedeutet: nachdem ein nested-context <i>geöffnet wurde, </i>müssen wir einen State erlangen, auf dem transparent genauso gearbeitet werden kann, wie auf dem initialen / top-level-State
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1710803573890" ID="ID_331230947" MODIFIED="1710803577253" TEXT="Iter">
|
||||
<node CREATED="1710803580073" ID="ID_92823392" MODIFIED="1710803623176" TEXT="Auswertungszustand auf der DataSrc"/>
|
||||
<node CREATED="1710803710216" ID="ID_1903129970" MODIFIED="1710803728139" TEXT="kann dereferenziert werden ⟼ string-konvertierbar"/>
|
||||
<node CREATED="1710803743860" ID="ID_408889688" MODIFIED="1710803759710" TEXT="kann auf »Gehalt« geprüft werden ⟼ bool"/>
|
||||
<node CREATED="1710803768785" ID="ID_1240137544" MODIFIED="1710803786266" TEXT="kann u.U iteriert werden">
|
||||
<node CREATED="1710803789014" ID="ID_871294739" MODIFIED="1710803797988" TEXT="findet aber nur in der Sequenz statt"/>
|
||||
<node CREATED="1710803768785" ID="ID_1240137544" MODIFIED="1710888759444" TEXT="kann iteriert werden (Iterator-Protokoll)">
|
||||
<node CREATED="1710803799133" ID="ID_16257402" MODIFIED="1710803811694" TEXT="nur ein gehaltvoller Iterator darf Iteriert werden"/>
|
||||
<node CREATED="1710803812469" ID="ID_776439841" MODIFIED="1710803820957" TEXT="nach der Iteration muß erneut auf Gehalt geprüft werden"/>
|
||||
</node>
|
||||
<node CREATED="1710888766407" ID="ID_1542277193" MODIFIED="1710888791904" TEXT="kann »geöffnet« werden ⟼ nested DataSrc">
|
||||
<node CREATED="1710888800147" ID="ID_415681901" MODIFIED="1710888817940" TEXT="konzeptionell wie eine Dreferentiation"/>
|
||||
<node CREATED="1710888818840" ID="ID_480044105" MODIFIED="1710888865476" TEXT="aber die Implementierung obliegt der DataSrc">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
weil sie im Einzelfall auch komplexer sein kann, und im Besonderen eine parent-Verknüpfung beinhaltet
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1710803901743" ID="ID_1926090539" MODIFIED="1710803921865" TEXT="jeder Datentyp, welcher diese Eigenschaften bietet, kann als Datenbinding fungieren">
|
||||
|
|
@ -112831,35 +112861,79 @@ std::cout << tmpl.render({"what", "World"}) << s
|
|||
<node CREATED="1710856916531" ID="ID_1047340326" MODIFIED="1710856926342" TEXT="die ActionSeq konsumieren"/>
|
||||
<node CREATED="1710857877562" ID="ID_707601175" MODIFIED="1710857911451" TEXT="Instantiierungs-Prozessor : function-mapping"/>
|
||||
<node CREATED="1710858136177" ID="ID_1016066994" MODIFIED="1710858673982" TEXT="logische Signatur des Einzelschrits: (Action, Binding, Ctx) ⟼ string"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1710858917164" ID="ID_1301011429" MODIFIED="1710859941873" TEXT="praktischer Ansatz: IterableDecorator über DataBind">
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1710858917164" ID="ID_1301011429" MODIFIED="1710889523599" TEXT="praktischer Ansatz: IterableDecorator einer InscanceCore">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1710859059558" ID="ID_878052078" MODIFIED="1710859508605" TEXT="das ist das konkrete Binding">
|
||||
<node CREATED="1710859078771" ID="ID_283747990" MODIFIED="1710859082314" TEXT="ist move-only"/>
|
||||
<node CREATED="1710889530609" ID="ID_1033056147" MODIFIED="1710889545299" TEXT="diese beinhaltet den Interpreter-State"/>
|
||||
<node CREATED="1710889546263" ID="ID_1579638728" MODIFIED="1710889557098" TEXT="einschließlich der Möglichkeit verschachtelter States"/>
|
||||
<node CREATED="1710889557878" ID="ID_1797783109" MODIFIED="1710889645948" TEXT="letzteres ist aber als seltene/optionale Erweiterung anzusetzen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
will sagen, der Standardfall ist, lediglich auf eine Map per Key zuzugreifen — und die gesamte Datenstruktur ist hierauf zu optimieren
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1710859059558" ID="ID_878052078" MODIFIED="1710889700823" TEXT="eingebettete DataSrc ≡ das ist das konkrete Binding">
|
||||
<node CREATED="1710859078771" ID="ID_283747990" MODIFIED="1710889722804" TEXT="ist zuweisbar (für nesting)"/>
|
||||
<node CREATED="1710859083131" ID="ID_1103676674" MODIFIED="1710859102540" TEXT="const- referenziert die Daten"/>
|
||||
<node CREATED="1710859106953" ID="ID_1570382274" MODIFIED="1710859128336" TEXT="implementiert das Binding-Concept"/>
|
||||
</node>
|
||||
<node CREATED="1710859515737" ID="ID_1401350564" MODIFIED="1710859521900" TEXT="enthält eine DataSrc">
|
||||
<node CREATED="1710859523200" ID="ID_1772496628" MODIFIED="1710859542793" TEXT="diese referenziert die Daten"/>
|
||||
<node CREATED="1710859544029" ID="ID_1522505977" MODIFIED="1710859550400" TEXT="ist aber assignable"/>
|
||||
<node CREATED="1710859551122" ID="ID_602535289" MODIFIED="1710859562631" TEXT="und implementiert die Binding-Funktionalität"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1710859064221" ID="ID_190332829" MODIFIED="1710859956662" TEXT="hält außerdem einen DataSrc::Iter">
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1710859064221" ID="ID_190332829" MODIFIED="1710889769933" TEXT="stellt außerdem einen Stack für Verschachtelung bereit">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node CREATED="1710889849728" ID="ID_399157295" MODIFIED="1710889858546" TEXT="falls leer ⟹ einfacher Standardfall"/>
|
||||
<node CREATED="1710889859678" ID="ID_1032750724" MODIFIED="1710889877399" TEXT="sonst: muß sich jeweils die Vorgänger-DataSrc merken"/>
|
||||
<node CREATED="1710889878990" ID="ID_936276949" MODIFIED="1710889900005" TEXT="...um diese vor dem pop() wiederherstellen zu können"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1710901560145" ID="ID_783804444" MODIFIED="1710901575026" TEXT="puh .... mühsam">
|
||||
<icon BUILTIN="smiley-angry"/>
|
||||
<node CREATED="1710901576799" ID="ID_309524144" MODIFIED="1710901587322" TEXT="überall beißt sich die Katze in den Schwanz"/>
|
||||
<node CREATED="1710901588837" ID="ID_1966885383" MODIFIED="1710901606703" TEXT="ich will die Implementierungs-Logik möglichst weit nach unten schieben"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1710898561618" ID="ID_961175411" MODIFIED="1710898581408" TEXT="Optimierung: string_view durch das ganze System durchfädeln">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1710898588958" ID="ID_329918455" MODIFIED="1710898606712" TEXT="es läuft stets auf einen koordinierten Datenzugriff hinaus"/>
|
||||
<node CREATED="1710898607588" ID="ID_1515577566" MODIFIED="1710898620430" TEXT="und die Datenstruktur wird referenziert während der Instantiierung"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710898624785" ID="ID_153699526" MODIFIED="1710898818451" TEXT="⟹ theoretisch sollte es möglich sein durch den gesamten Prozeß hindurch zu referenzieren">
|
||||
<node CREATED="1710898727250" ID="ID_1040294627" MODIFIED="1710898736225" TEXT="die Keys sind zwar kurz..."/>
|
||||
<node CREATED="1710898736874" ID="ID_379388881" MODIFIED="1710898751668" TEXT="aber die konstanten Template-Bestandteile sind (sehr) lang"/>
|
||||
<node CREATED="1710898758439" ID="ID_40861357" MODIFIED="1710898781000" TEXT="mit String-Values würde zudem auf vielen Ebenen kopiert und Heap-Memory verwaltet"/>
|
||||
<node CREATED="1710898782460" ID="ID_1183887615" MODIFIED="1710901418729" TEXT="und letztlich verlangt auch das Iterator-Konzept eine Referenz vom »core-yield«">
|
||||
<arrowlink COLOR="#756ac6" DESTINATION="ID_98335183" ENDARROW="Default" ENDINCLINATION="63;-36;" ID="Arrow_ID_506603112" STARTARROW="None" STARTINCLINATION="-260;10;"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1710898830750" ID="ID_629945091" MODIFIED="1710898839421" TEXT="ist das auch praktisch machbar?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1710901352781" ID="ID_98335183" MODIFIED="1710901434035" TEXT="muß es schon deshalb machen, weil das Rendern einmalig bei der Iteration passiert">
|
||||
<linktarget COLOR="#756ac6" DESTINATION="ID_98335183" ENDARROW="Default" ENDINCLINATION="63;-36;" ID="Arrow_ID_506603112" SOURCE="ID_1183887615" STARTARROW="None" STARTINCLINATION="-260;10;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1710856784967" ID="ID_201927694" MODIFIED="1710856798759" TEXT="Parsing soll eager sein (wegen Syntax-Fehlern)"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1710901479260" ID="ID_1390433932" MODIFIED="1710901499394" TEXT="Action::instantiate() auf Basis des Data-Bindings implementieren">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710901502001" ID="ID_1137356719" MODIFIED="1710901531737" TEXT="hier wird der Kern der Template-Interpretation ausformuliert">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710793352301" ID="ID_1691061928" MODIFIED="1710793355254" TEXT="Bindings">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710793356309" ID="ID_618241969" MODIFIED="1710793358557" TEXT="Map">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1710804031539" ID="ID_1692068622" MODIFIED="1710804061062" TEXT="der Inhaltstyp wird auf via util::toString() zugegriffen"/>
|
||||
<node CREATED="1710804031539" ID="ID_1692068622" MODIFIED="1710879172991" TEXT="der Inhaltstyp wird via util::toString() zugegriffen"/>
|
||||
<node CREATED="1710804062496" ID="ID_377899149" MODIFIED="1710804093937" TEXT="DataSrc ist ein generischer Wrapper um die Map"/>
|
||||
<node CREATED="1710804167972" ID="ID_200600045" MODIFIED="1710804186992" TEXT="der Iterator ist eine String-View (ein String-Range)"/>
|
||||
<node CREATED="1710804197208" ID="ID_709716942" MODIFIED="1710804233519" TEXT="Sequenz-Auswertung interpretiert den String als CSV-Zeile"/>
|
||||
<node CREATED="1710804454510" ID="ID_835685377" MODIFIED="1710804469839" TEXT="die einzelnen Datenelemente werden als Key-Präfix interpretiert"/>
|
||||
<node CREATED="1710804454510" ID="ID_835685377" MODIFIED="1710879851836" TEXT="die einzelnen Sequenz-Elemente werden als Key-Präfix interpretiert"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1710804234267" ID="ID_226073889" MODIFIED="1710804261633" TEXT="Verschachtelung wird nicht unterstützt">
|
||||
<icon BUILTIN="yes"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue