Library: add generic chaining
* need to pass the parse end-point in the Eval-Result to allow composed models * this also prepares for support of generic model-binding-λ With the help of the model-joining case definitions it is then possible to handle sequence extension. Deliberately I do not engage into fine grained signature checking, since this would lead to very technical code and moreover this is an implementation feature and we control all invocations (with signatures guaranteed to be correct)
This commit is contained in:
parent
7998c8d724
commit
fb78c10996
3 changed files with 140 additions and 22 deletions
|
|
@ -59,6 +59,7 @@ namespace util {
|
|||
{
|
||||
using Result = RES;
|
||||
optional<RES> result;
|
||||
size_t consumed{0};
|
||||
};
|
||||
|
||||
template<class FUN>
|
||||
|
|
@ -91,7 +92,9 @@ namespace util {
|
|||
return Connex{[regEx = move(rex)]
|
||||
(StrView toParse) -> Eval<smatch>
|
||||
{
|
||||
return {matchAtStart (toParse,regEx)};
|
||||
auto result{matchAtStart (toParse,regEx)};
|
||||
size_t consumed = result? result->length() : 0;
|
||||
return {move(result), consumed};
|
||||
}};
|
||||
}
|
||||
using Term = decltype(buildConnex (std::declval<regex>()));
|
||||
|
|
@ -120,9 +123,9 @@ namespace util {
|
|||
auto
|
||||
adaptConnex (CON&& connex, BIND&& modelBinding)
|
||||
{
|
||||
using R1 = typename CON::Result;
|
||||
using RX = typename CON::Result;
|
||||
using Arg = lib::meta::_FunArg<BIND>;
|
||||
static_assert (std::is_constructible_v<Arg,R1>,
|
||||
static_assert (std::is_constructible_v<Arg,RX>,
|
||||
"Model binding must accept preceding model result.");
|
||||
using AdaptedRes = typename _Fun<BIND>::Ret;
|
||||
return Connex{[origConnex = forward<CON>(connex)
|
||||
|
|
@ -153,7 +156,20 @@ namespace util {
|
|||
using Seq = lib::meta::TySeq<RESULTS...>;
|
||||
using Tup = std::tuple<RESULTS...>;
|
||||
|
||||
using Tup::Tup;
|
||||
SeqModel() = default;
|
||||
|
||||
template<typename...XS, typename XX>
|
||||
SeqModel (SeqModel<XS...>&& seq, XX&& extraElm)
|
||||
: Tup{std::tuple_cat (seq.extractTuple()
|
||||
,make_tuple (forward<XX> (extraElm)) )}
|
||||
{ }
|
||||
|
||||
template<typename X1, typename X2>
|
||||
SeqModel (X1&& res1, X2&& res2)
|
||||
: Tup{move(res1), move(res2)}
|
||||
{ }
|
||||
|
||||
Tup&& extractTuple() { return move(*this); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -237,14 +253,16 @@ namespace util {
|
|||
auto eval1 = conL.parse (toParse);
|
||||
if (eval1.result)
|
||||
{
|
||||
uint end1 = eval1.result->length();/////////////////////////OOO pass that via Eval
|
||||
StrView restInput = toParse.substr(end1);
|
||||
size_t posAfter1 = eval1.consumed;
|
||||
StrView restInput = toParse.substr(posAfter1);
|
||||
auto eval2 = conR.parse (restInput);
|
||||
if (eval2.result)
|
||||
{
|
||||
uint end2 = end1 + eval2.result->length();
|
||||
uint consumedOverall = posAfter1 + eval2.consumed;
|
||||
return ProductEval{ProductResult{move(*eval1.result)
|
||||
,move(*eval2.result)}};
|
||||
,move(*eval2.result)}
|
||||
,consumedOverall
|
||||
};
|
||||
}
|
||||
}
|
||||
return ProductEval{std::nullopt};
|
||||
|
|
|
|||
|
|
@ -146,20 +146,23 @@ namespace test {
|
|||
auto eval1 = term1.parse (toParse);
|
||||
if (eval1.result)
|
||||
{
|
||||
uint end1 = eval1.result->length();
|
||||
uint end1 = eval1.consumed;
|
||||
StrView restInput = toParse.substr(end1);
|
||||
auto eval2 = term2.parse (restInput);
|
||||
if (eval2.result)
|
||||
{
|
||||
uint end2 = end1 + eval2.result->length();
|
||||
uint consumedOverall = end1 + eval2.consumed;
|
||||
return ProductEval{ProductResult{move(*eval1.result)
|
||||
,move(*eval2.result)}};
|
||||
,move(*eval2.result)}
|
||||
,consumedOverall
|
||||
};
|
||||
}
|
||||
}
|
||||
return ProductEval{std::nullopt};
|
||||
};
|
||||
string s1{"hello millions"};
|
||||
string s2{"helloworld"};
|
||||
string s3{"helloworldtrade"};
|
||||
|
||||
auto e1 = parseSeq(s1);
|
||||
CHECK (not e1.result);
|
||||
|
|
@ -182,6 +185,17 @@ namespace test {
|
|||
SeqRes seqModel = syntax.getResult();
|
||||
CHECK (get<0>(seqModel).str() == "hello"_expect);
|
||||
CHECK (get<1>(seqModel).str() == "world"_expect);
|
||||
|
||||
auto syntax2 = syntax.seq("trade");
|
||||
CHECK (not syntax2.hasResult());
|
||||
syntax2.parse(s2);
|
||||
CHECK (not syntax2.success());
|
||||
syntax2.parse(s3);
|
||||
CHECK (syntax2.success());
|
||||
auto seqModel2 = syntax2.getResult();
|
||||
CHECK (get<0>(seqModel2).str() == "hello"_expect);
|
||||
CHECK (get<1>(seqModel2).str() == "world"_expect);
|
||||
CHECK (get<2>(seqModel2).str() == "trade"_expect);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -55511,10 +55511,12 @@
|
|||
<node CREATED="1736897797339" ID="ID_1097974753" MODIFIED="1736897811257" TEXT="brauche Zugang zu den Parse-Funktoren"/>
|
||||
<node CREATED="1736902653470" ID="ID_755819552" MODIFIED="1736902670961" TEXT="Ende des akzeptierten Strings">
|
||||
<node CREATED="1736902672230" ID="ID_1913745367" MODIFIED="1736902683365" TEXT="zunächst einmal: vom Match-Result"/>
|
||||
<node CREATED="1736902693644" ID="ID_808818374" MODIFIED="1736902710074" TEXT="würde durch custom-Result-Binding unterlaufen"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1736902716749" ID="ID_805311488" MODIFIED="1737132872474" TEXT="brauche daher diese Position explizit im Ergebnis">
|
||||
<linktarget COLOR="#e61b59" DESTINATION="ID_805311488" ENDARROW="Default" ENDINCLINATION="513;28;" ID="Arrow_ID_936843613" SOURCE="ID_1822754637" STARTARROW="None" STARTINCLINATION="339;-15;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1736902693644" ID="ID_808818374" MODIFIED="1737169308735" TEXT="würde durch custom-Result-Binding unterlaufen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1736902716749" ID="ID_805311488" MODIFIED="1737169317794" TEXT="brauche daher diese Position explizit im Ergebnis">
|
||||
<linktarget COLOR="#1b33e6" DESTINATION="ID_805311488" ENDARROW="Default" ENDINCLINATION="513;28;" ID="Arrow_ID_936843613" SOURCE="ID_1822754637" STARTARROW="None" STARTINCLINATION="339;-15;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1736902736554" ID="ID_432853835" MODIFIED="1736902758544" TEXT="erst einmal explizit als Lambda für zwei Parse-Funktionen ausformuliert">
|
||||
|
|
@ -55902,22 +55904,106 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737048292893" ID="ID_387462355" MODIFIED="1737124700525" TEXT="Model-Inkrement konkret als tuple_cat realisieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737048292893" ID="ID_387462355" MODIFIED="1737169984121" TEXT="Model-Inkrement konkret als tuple_cat realisieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1737132764886" ID="ID_975789323" MODIFIED="1737132784921" TEXT="erster Schritt: Tupel aus zwei Sub-Klauseln konstruieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737132793799" ID="ID_1822754637" MODIFIED="1737132872474" TEXT="brauche nun Verallgemeinerung für Model-Binding">
|
||||
<arrowlink COLOR="#e61b59" DESTINATION="ID_805311488" ENDARROW="Default" ENDINCLINATION="513;28;" ID="Arrow_ID_936843613" STARTARROW="None" STARTINCLINATION="339;-15;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1737132793799" ID="ID_1822754637" MODIFIED="1737169335359" TEXT="brauche nun Verallgemeinerung für Model-Binding">
|
||||
<arrowlink COLOR="#1b33e6" DESTINATION="ID_805311488" ENDARROW="Default" ENDINCLINATION="513;28;" ID="Arrow_ID_936843613" STARTARROW="None" STARTINCLINATION="339;-15;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1737169353949" ID="ID_1970086696" MODIFIED="1737169373283" TEXT="zweiter Schritt: Erweiterung bestehener Sequenzen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1737169399361" ID="ID_1743070973" MODIFIED="1737169580689" TEXT="sehr schwierig korrekt zu formulieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...weil wir die Typen ja permanent umbauen;
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
 man müßte hier massiv mit Typsequenzen programmieren, um eine präzise, erwartete Signatur zu konstruieren;
|
||||
</li>
|
||||
<li>
|
||||
alternativ könnte man in die _Join - Rebinder-Templates noch eine explizite cons-Funktion mit aufnehmen (dann hätte man aber das gleiche Problem hier)
|
||||
</li>
|
||||
<li>
|
||||
oder man könnte alle Argumente durch eine lift()-Hilfsfunktion schieben, die dann aber mit den möglichen Models verkoppelt wäre
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1737169407433" ID="ID_1120580246" MODIFIED="1737169863854" TEXT="aber einfach wenn man auf explizite Signatur-Checks verzichtet">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Das wäre schon denkbar, da wir alle Aufrufe hier kontrollieren — und diese Model-Klassen nicht außerhalb des Parsers verwendet werden sollten, sondern nur in den Combinatoren selber und (lesend) in Binding-λ.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Im Fall des SeqModel gibt es noch ein zusätzliches Sicherheitsnetz, da wir von einem explizit getypten Tupel erben.
|
||||
</li>
|
||||
<li>
|
||||
Im Fall des AltModel gibt es <b>kein</b> direktes Sicherheitsnetz, weil wir »blind« in eine Variant-Storage schreiben werden. Man sollte dann noch einen Check auf den Selektor realisieren
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<arrowlink COLOR="#b52e62" DESTINATION="ID_1565968263" ENDARROW="Default" ENDINCLINATION="-20;-92;" ID="Arrow_ID_43564391" STARTARROW="None" STARTINCLINATION="74;-2;"/>
|
||||
</node>
|
||||
<node CREATED="1737169424955" ID="ID_5139254" MODIFIED="1737169443329" TEXT="das ist hier angemessen; es handelt sich um ein Implementierungsdetail">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1737169797084" ID="ID_1565968263" MODIFIED="1737169855695" TEXT="Check auf Selektor bei AltModel notwendig">
|
||||
<linktarget COLOR="#b52e62" DESTINATION="ID_1565968263" ENDARROW="Default" ENDINCLINATION="-20;-92;" ID="Arrow_ID_43564391" SOURCE="ID_1120580246" STARTARROW="None" STARTINCLINATION="74;-2;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737048329300" ID="ID_250317778" MODIFIED="1737048343967" TEXT="in Builder-DSL formulieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1737048329300" ID="ID_250317778" MODIFIED="1737170104778" TEXT="in Builder-DSL formulieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1737170001654" ID="ID_196586019" MODIFIED="1737170006419" TEXT="Syntax::seq()"/>
|
||||
<node COLOR="#435e98" CREATED="1737170034742" ID="ID_140940144" MODIFIED="1737170100878" TEXT="Trick: accept() akzeptiert alles für Parser-ctor ... also auch einen Connex">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1737170063277" ID="ID_764192769" MODIFIED="1737170102489" TEXT="damit ist die Formulierung einfach und die Logik steckt in sequenceConnex()">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node CREATED="1737170091633" ID="ID_1805045209" MODIFIED="1737170095378" TEXT="gefällt mir">
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1737048838728" ID="ID_327712073" MODIFIED="1737048870554" TEXT="automatisch Whitespace absorbieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#5b280f" CREATED="1737170123805" ID="ID_4605321" MODIFIED="1737170139588" TEXT="theoretisch könnte man Whitespace-Trenner sogar mandatory machen">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1737170144395" ID="ID_620070055" MODIFIED="1737170158073" TEXT="dann braucht man aber auch wieder einen Mechanismus zum Abschalten"/>
|
||||
<node CREATED="1737170158776" ID="ID_1917215183" MODIFIED="1737170176093" TEXT="also besser nicht ..."/>
|
||||
<node CREATED="1737170176950" ID="ID_1322159995" MODIFIED="1737170226429" TEXT="im Zweifelsfall muß man in der RegExp explizit mit einer lookbehind-Assertion arbeiten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
oder mit \\b
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1737048362231" ID="ID_751583918" MODIFIED="1737048461620" TEXT="funktioniert im Test">
|
||||
<arrowlink DESTINATION="ID_1506892827" ENDARROW="Default" ENDINCLINATION="44;-70;" ID="Arrow_ID_283520954" STARTARROW="None" STARTINCLINATION="-17;2;"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue