Library: connect both parts of the engine

...gets the hello-world test to run
This commit is contained in:
Fischlurch 2024-03-24 23:05:16 +01:00
parent 20f2b1b90a
commit 8d432a6e0b
3 changed files with 40 additions and 25 deletions

View file

@ -45,9 +45,12 @@
namespace lib {
namespace {// Implementation of the access core
namespace iter {
/**
* Implementation of a »IterStateCore«
* to access the container through an embedded index variable.
*/
template<typename PTR>
struct IndexAccessCore
{
@ -116,9 +119,9 @@ namespace lib {
*/
template<class CON, typename PTR = CON*>
class IterIndex
: public IndexAccessCore<PTR>::IterWrapper
: public iter::IndexAccessCore<PTR>::IterWrapper
{
using _Cor = IndexAccessCore<PTR>;
using _Cor = iter::IndexAccessCore<PTR>;
using _Par = typename _Cor::IterWrapper;
public:

View file

@ -286,8 +286,11 @@ namespace lib {
template<class DAT>
using InstanceIter = ExploreIter<InstanceCore<DataSource<DAT>>>;
ActionSeq actions_;
public:
TextTemplate(string spec)
: actions_{compile (spec)}
{ }
template<class DAT>
@ -298,6 +301,7 @@ namespace lib {
static string
apply (string spec, DAT const& data);
static ActionSeq compile (string const&);
friend class test::TextTemplate_test;
};
@ -461,6 +465,15 @@ namespace lib {
} // add final action to supply text after last active tag
};
inline TextTemplate::ActionSeq
TextTemplate::compile (string const& spec)
{
ActionSeq code = ActionCompiler().buildActions (parse (spec));
if (isnil (code))
throw error::Invalid ("TextTemplate spec without active placeholders.");
return code;
}
@ -479,7 +492,7 @@ namespace lib {
template<>
struct TextTemplate::DataSource<MapS>
{
MapS* data_;
MapS const * data_;
using Iter = std::string_view;
bool
@ -491,7 +504,9 @@ namespace lib {
string const&
retrieveContent (string key)
{
return (*data_)[key];
auto elm = data_->find (key);
ENSURE (elm != data_->end());
return elm->second;
}
};
@ -533,7 +548,7 @@ namespace lib {
template<class SRC>
TextTemplate::InstanceCore<SRC>::InstanceCore (TextTemplate::ActionSeq const& actions, SRC s)
: dataSrc_{s}
, actionIter_{explore (actions)}
, actionIter_{actions}
, ctxStack_{}
, rendered_{}
{
@ -587,12 +602,14 @@ namespace lib {
/** */
/**
* Instantiate this (pre-compiled) TextTemplate using the given data binding.
*/
template<class DAT>
inline TextTemplate::InstanceIter<DAT>
TextTemplate::render (DAT const& data) const
{
UNIMPLEMENTED ("actually instantiate the text template");
return explore (InstanceCore{actions_, DataSource<DAT>{&data}});
}
/** */

View file

@ -67,7 +67,7 @@ namespace test {
virtual void
run (Arg)
{
// simpeUsage();
simpeUsage();
verify_parsing();
verify_instantiation();
verify_keySubstituton();
@ -79,8 +79,8 @@ namespace test {
}
/** @test TODO simple point-and-shot usage...
* @todo WIP 4/24 define 🔁 implement
/** @test simple point-and-shot usage...
* @todo WIP 4/24 define implement
*/
void
simpeUsage()
@ -92,7 +92,7 @@ namespace test {
}
/** @test TODO
/** @test parsing of tag markup and compilation into a sequence of Action-codes
* @note the regular expression \ref ACCEPT_FIELD is comprised of several
* alternatives and optional parts, which are marked by 5 sub-expressions
* - 1 an escaped field (which should not be processed)
@ -100,7 +100,7 @@ namespace test {
* - 3 end token
* - 4 some logic token ("if" or "for")
* - 5 a key or key path
* @todo WIP 4/24 🔁 define implement
* @todo WIP 4/24 define implement
*/
void
verify_parsing()
@ -118,7 +118,7 @@ namespace test {
CHECK (mat.length() == 7);
CHECK (mat.prefix() == " stale"_expect);
CHECK (mat.suffix() == "forever"_expect);
CHECK (mat[0] == "${beer}"_expect); // so this first example demonstrates placeholder recognition
CHECK (mat[0] == "${beer}"_expect); // so this first example demonstrates placeholder recognition
CHECK (not mat[1].matched); // Sub-1 : this is not an escaped pattern
CHECK (not mat[2].matched); // Sub-2 : this pattern does not start with "else"
CHECK (not mat[3].matched); // Sub-3 : no "end" keyword
@ -177,7 +177,7 @@ namespace test {
CHECK (mat.position() == 24);
CHECK (mat.length() == 2);
CHECK (mat.prefix() == " catch ${else if} fever "_expect); // Note: first pattern does not match as "else" must be solitary
CHECK (mat.suffix() == "{can.beer} "_expect); // Note: the following braced expression is tossed aside
CHECK (mat.suffix() == "{can.beer} "_expect); // Note: the following braced expression is tossed aside
CHECK (mat[0] == "\\$"_expect); // Only the escaped pattern mark opening is picked up
CHECK (not mat[2].matched);
CHECK (not mat[3].matched);
@ -186,6 +186,7 @@ namespace test {
CHECK (mat[1] == "\\$"_expect); // Sub-1 picks the escaped mark (and the remainder is no complete tag)
// Demonstration: can use this regular expression in a matching pipeline....
input = "one ${two} three \\${four} ${if high} five";
CHECK (util::join(
@ -196,7 +197,7 @@ namespace test {
// Parse matches of this regexp into well defined syntax elements
auto parser = parse(input);
auto parser = parse (input);
CHECK (not isnil(parser));
CHECK (parser->syntax == TagSyntax::KEYID);
CHECK (parser->lead == "one "_expect);
@ -217,13 +218,8 @@ namespace test {
VERIFY_ERROR (ITER_EXHAUST, ++parser);
// Generate sequence of Action tokens from parsing results
auto render = [](TextTemplate::Action const& act) -> string
{ return _Fmt{"‖%d|↷%d‖▷%s"} % uint(act.code) % act.refIDX % act.val; };
auto act1 = TextTemplate::ActionCompiler().buildActions(parse(input));
SHOW_EXPR(util::join(explore(act1)
.transform(render)
, ""))
input = R"~(
Prefix-1 ${some.key} next one is \${escaped}
Prefix-2 ${if cond1} active ${else} inactive ${end if
@ -234,8 +230,7 @@ SHOW_EXPR(util::join(explore(act1)
if nested}loop-suffix${else}${end
for} tail...
)~";
auto actions = TextTemplate::ActionCompiler().buildActions(parse(input));
SHOW_EXPR(util::join (explore(actions).transform(render),"\n"))
auto actions = TextTemplate::compile (input);
CHECK (25 == actions.size());
CHECK (actions[ 0].code == TextTemplate::Code::TEXT);