Library: further straighten iteration logic
playing the »fence post problem« the other way round and abandoning the ''pull processing'' in favour of direct manipulation leads to much clearer formulation of the code-generation logic
This commit is contained in:
parent
bc8e947f3c
commit
aab446ce48
2 changed files with 45 additions and 54 deletions
|
|
@ -316,7 +316,6 @@ namespace lib {
|
|||
*/
|
||||
class TextTemplate::ActionCompiler
|
||||
{
|
||||
Idx idx_{0};
|
||||
ScopeStack scope_{};
|
||||
|
||||
public:
|
||||
|
|
@ -325,83 +324,72 @@ namespace lib {
|
|||
buildActions (PAR&& parseIter)
|
||||
{
|
||||
ActionSeq actions;
|
||||
actions.emplace_back (Action{TEXT, initLead(parseIter)});
|
||||
while (parseIter)
|
||||
{
|
||||
idx_ = actions.size();
|
||||
actions.emplace_back(
|
||||
compile (parseIter, actions.back().code));
|
||||
}
|
||||
compile (parseIter, actions);
|
||||
return actions;
|
||||
}
|
||||
|
||||
private:
|
||||
template<class PAR>
|
||||
Action
|
||||
compile (PAR& parseIter, Code currCode)
|
||||
{ //...throws if exhausted
|
||||
TagSyntax& tag = *parseIter;
|
||||
auto isState = [&](Code c){ return c == currCode; };
|
||||
auto nextState = [&] {
|
||||
StrView lead = tag.tail;
|
||||
++parseIter;
|
||||
// first expose intermittent text before next tag
|
||||
if (parseIter)
|
||||
lead = parseIter->lead;
|
||||
return Action{TEXT, string{lead}};
|
||||
};
|
||||
switch (tag.syntax) {
|
||||
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()});};
|
||||
|
||||
switch (parseIter->syntax) {
|
||||
case TagSyntax::ESCAPE:
|
||||
return nextState();
|
||||
addLead();
|
||||
break;
|
||||
case TagSyntax::KEYID:
|
||||
if (isState (KEY))
|
||||
return nextState();
|
||||
return Action{KEY, tag.key};
|
||||
addLead();
|
||||
addCode(KEY);
|
||||
break;
|
||||
case TagSyntax::IF:
|
||||
if (isState (COND))
|
||||
return nextState();
|
||||
///////////////////////////////////////////////////OOO push IF-clause here
|
||||
scope_.push (ParseCtx{IF, idx_});
|
||||
return Action{COND, tag.key};
|
||||
addLead();
|
||||
openScope(IF);
|
||||
addCode(COND);
|
||||
break;
|
||||
case TagSyntax::END_IF:
|
||||
addLead();
|
||||
///////////////////////////////////////////////////OOO verify and pop IF-clause here
|
||||
// if (scope_.empty() or
|
||||
// (not isnil(tag.key) scope_.top())
|
||||
return nextState();
|
||||
break;
|
||||
case TagSyntax::FOR:
|
||||
if (isState (ITER))
|
||||
return nextState();
|
||||
addLead();
|
||||
openScope(FOR);
|
||||
///////////////////////////////////////////////////OOO push FOR-clause here
|
||||
return Action{ITER, tag.key};
|
||||
addCode(ITER);
|
||||
break;
|
||||
case TagSyntax::END_FOR:
|
||||
addLead();
|
||||
///////////////////////////////////////////////////OOO verify and pop FOR-clause here
|
||||
return nextState();
|
||||
break;
|
||||
case TagSyntax::ELSE:
|
||||
addLead();
|
||||
if (true) /////////////////////////////////////////OOO derive IF or FOR from context
|
||||
{
|
||||
if (isState (JUMP))
|
||||
return nextState();
|
||||
///////////////////////////////////////////////////OOO actual IF-else implementation
|
||||
return Action{JUMP};
|
||||
addCode(JUMP);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isState (LOOP))
|
||||
return nextState();
|
||||
///////////////////////////////////////////////////OOO actual FOR-else implementation
|
||||
return Action{LOOP};
|
||||
addCode(LOOP);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NOTREACHED ("uncovered TagSyntax keyword while compiling a TextTemplate.");
|
||||
}
|
||||
}
|
||||
|
||||
template<class PAR>
|
||||
string
|
||||
initLead (PAR& parseIter) ///< first Action must present the literal text before the first tag
|
||||
{
|
||||
return string{parseIter? parseIter->lead : ""};
|
||||
}
|
||||
|
||||
StrView tail = parseIter->tail;
|
||||
++parseIter;
|
||||
if (not parseIter)
|
||||
add (TEXT, string{tail});
|
||||
} // add final action to supply text after last active tag
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -113259,13 +113259,16 @@ std::cout << tmpl.render({"what", "World"}) << s
|
|||
<node CREATED="1711283145848" ID="ID_493051003" MODIFIED="1711283157218" TEXT="ehrlich gesagt: es war schon ganz schön komplex"/>
|
||||
<node CREATED="1711283158094" ID="ID_316804248" MODIFIED="1711283210930" TEXT="wiewohl im Rahmen des Iterator-Schemas (für mich) verständlich"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711283024446" ID="ID_559056931" MODIFIED="1711283047068" TEXT="stattdessen: den Compiler als Builder-Komponente anlegen">
|
||||
<node COLOR="#338800" CREATED="1711283024446" ID="ID_559056931" MODIFIED="1711291844432" TEXT="stattdessen: den Compiler als Builder-Komponente anlegen">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711283086632" ID="ID_396780439" MODIFIED="1711283215456" TEXT="erzeugen als freie (kopierbare) Komponente">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1711283086632" ID="ID_396780439" MODIFIED="1711291784325" TEXT="erzeugen als freie (kopierbare) Komponente">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1711283101287" ID="ID_1709357131" MODIFIED="1711283215456" TEXT="Arbeitsmethode: buildActions(ParseIterator)">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1711283101287" ID="ID_1709357131" MODIFIED="1711291786010" TEXT="Arbeitsmethode: buildActions(ParseIterator)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1711291788419" ID="ID_1652146964" MODIFIED="1711291834531" TEXT="das »funktionale« pull-Processing aufgeben ⟹ Code viel klarer">
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue