diff --git a/src/lib/parse.hpp b/src/lib/parse.hpp index 1ea929043..4b07d8745 100644 --- a/src/lib/parse.hpp +++ b/src/lib/parse.hpp @@ -59,6 +59,7 @@ namespace util { { using Result = RES; optional result; + size_t consumed{0}; }; template @@ -91,7 +92,9 @@ namespace util { return Connex{[regEx = move(rex)] (StrView toParse) -> Eval { - 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())); @@ -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; - static_assert (std::is_constructible_v, + static_assert (std::is_constructible_v, "Model binding must accept preceding model result."); using AdaptedRes = typename _Fun::Ret; return Connex{[origConnex = forward(connex) @@ -153,7 +156,20 @@ namespace util { using Seq = lib::meta::TySeq; using Tup = std::tuple; - using Tup::Tup; + SeqModel() = default; + + template + SeqModel (SeqModel&& seq, XX&& extraElm) + : Tup{std::tuple_cat (seq.extractTuple() + ,make_tuple (forward (extraElm)) )} + { } + + template + 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}; diff --git a/tests/library/parse-test.cpp b/tests/library/parse-test.cpp index 5bbe609f7..6788f2dc1 100644 --- a/tests/library/parse-test.cpp +++ b/tests/library/parse-test.cpp @@ -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); } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index f9102277b..a6a59c0c4 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -55511,10 +55511,12 @@ - - - - + + + + + + @@ -55902,22 +55904,106 @@ - - + + - - - + + + + + + + + + + + + +

+ ...weil wir die Typen ja permanent umbauen; +

+
    +
  • +  man müßte hier massiv mit Typsequenzen programmieren, um eine präzise, erwartete Signatur zu konstruieren; +
  • +
  • + 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) +
  • +
  • + oder man könnte alle Argumente durch eine lift()-Hilfsfunktion schieben, die dann aber mit den möglichen Models verkoppelt wäre +
  • +
+ + +
+
+ + + + + + +

+ 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-λ. +

+
    +
  • + Im Fall des SeqModel gibt es noch ein zusätzliches Sicherheitsnetz, da wir von einem explizit getypten Tupel erben. +
  • +
  • + Im Fall des AltModel gibt es kein direktes Sicherheitsnetz, weil wir »blind« in eine Variant-Storage schreiben werden. Man sollte dann noch einen Check auf den Selektor realisieren +
  • +
+ + +
+ +
+ + + + +
- - + +
+ + + + + + + + + + + + + + + + + + + + + + +

+ oder mit \\b +

+ + +
+
+