247 return Connex{[regEx = move(rex)]
251 toParse = toParse.substr(pre);
253 size_t consumed = result? pre+result->length() : 0;
254 return {move(result), consumed};
277 return Connex{move(anchor)};
304 template<
typename ARG,
typename FUN,
typename SEL =
void>
307 static_assert (!
sizeof(ARG),
308 "Model binding must accept preceding model result.");
311 template<
typename ARG,
typename FUN>
314 using Ret =
decltype(std::declval<FUN>() (std::declval<ARG>()));
322 if constexpr (std::is_constructible<bool, FUN const&>())
325 return std::is_invocable<FUN, StrView>();
335 template<
class CON,
class BIND>
339 using RX = CON::Result;
340 using Arg = std::add_rvalue_reference_t<RX>;
341 using AdaptedRes = _ProbeFunReturn<Arg,BIND>::Ret;
342 return Connex{[origConnex = forward<CON>(connex)
343 ,binding = forward<BIND>(modelBinding)
347 auto eval = origConnex.parse (toParse);
349 return {binding (move (*eval.result))
352 return {std::nullopt};
360 using Result = CON::Result;
361 return Connex([baseConnex = forward<CON>(connex)
366 auto eval = baseConnex.parse (toParse);
369 return {eval.
result->str(part)
375 return {
string{toParse.substr (pre, eval.consumed - pre)}
380 return {std::nullopt};
392 template<
typename...RESULTS>
396 static constexpr size_t N =
sizeof...(RESULTS);
398 using Tup = std::tuple<RESULTS...>;
402 template<
typename...XS,
typename XX>
405 ,
std::make_tuple (forward<XX> (extraElm)) )}
408 template<
typename X1,
typename X2>
410 :
Tup{move(res1), move(res2)}
416 auto get() {
return std::get<i> (*
this); }
424 template<
typename...CASES>
429 static constexpr size_t N =
sizeof...(CASES);
431 template<
typename EXTRA>
434 template<
typename EXTRA>
439 return {move (upFaked)};
452 return {leftCases.template addBranch<Ultima>()};
458 return {
Alt::TOP-1, move(leftCase)};
468 template<
typename INIT>
470 :
Alt{branchID, forward<INIT> (init)}
476 template<
typename RES>
480 RES&
get (
size_t i) {
return this->at(i); }
484 template<
typename RES>
490 template<
template<
class...>
class TAG,
class R1,
class R2 =
void>
497 template<
template<
class...>
class TAG,
class...RS,
class R2>
504 template<
template<
class...>
class TAG,
class R1,
class R2>
509 template<
template<
class...>
class TAG,
class R1,
class R2>
514 template<
template<
class...>
class TAG,
class R1,
class R2>
523 template<
class C1,
class C2>
527 using R1 = decay_t<C1>::Result;
528 using R2 = decay_t<C2>::Result;
531 return Connex{[conL = forward<C1>(connex1)
532 ,conR = forward<C2>(connex2)
534 (
StrView toParse) -> ProductEval
536 auto eval1 = conL.
parse (toParse);
539 size_t posAfter1 = eval1.consumed;
540 StrView restInput = toParse.substr(posAfter1);
541 auto eval2 = conR.parse (restInput);
544 uint consumedOverall = posAfter1 + eval2.consumed;
545 return ProductEval{ProductResult{move(*eval1.result)
546 ,move(*eval2.result)}
551 return ProductEval{std::nullopt};
557 template<
class C1,
class C2>
561 using R1 = decay_t<C1>::Result;
562 using R2 = decay_t<C2>::Result;
565 return Connex{[conL = forward<C1>(connex1)
566 ,conR = forward<C2>(connex2)
570 auto eval1 = conL.
parse (toParse);
573 uint endBranch1 = eval1.consumed;
574 return SumEval{SumResult::mark_left (move(*eval1.result))
578 auto eval2 = conR.parse (toParse);
581 uint endBranch2 = eval2.consumed;
582 return SumEval{SumResult::mark_right (move(*eval2.result))
586 return SumEval{std::nullopt};
592 template<
class C1,
class C2>
598 using Res = decay_t<C2>::Result;
601 return Connex{[sep = forward<C1>(delimConnex)
602 ,body = forward<C2>(bodyConnex)
612 if (not results.empty())
614 auto delim = sep.
parse (toParse);
615 if (not delim.result)
617 offset += delim.consumed;
619 auto eval = body.parse (toParse.substr(offset));
622 offset += eval.consumed;
623 results.emplace_back (move(*eval.result));
624 toParse = toParse.substr(offset);
627 while (results.size() <
max);
628 return results.size() >=
min? IterEval{move(results), consumed}
629 : IterEval{std::nullopt};
639 using Res = decay_t<CNX>::Result;
640 using OptResult = optional<Res>;
642 return Connex{[body = forward<CNX>(connex)
646 auto eval = body.
parse (toParse);
647 size_t consumed{eval.result? eval.consumed : 0};
648 return OptEval{OptResult{eval.result? move(eval.result) : std::nullopt}
657 template<
class C1,
class C2,
class C3>
664 using Res = decay_t<C3>::Result;
665 return Connex{[opening = forward<C1>(openingConnex)
666 ,closing = forward<C2>(closingConnex)
667 ,body = forward<C3>(bodyConnex)
672 auto bracket = opening.parse (toParse);
673 if (bracket.result or isOptional)
676 bool expectClose{bracket.result};
677 auto eval = body.parse (toParse.substr(consumed));
680 consumed += eval.consumed;
682 bracket = closing.parse (toParse.substr(consumed));
683 if (bracket.result or not expectClose)
685 consumed += bracket.consumed;
708 static_assert (
_Fun<PFun>(),
"Connex must define a parse-function");
715 ,
"Signature of the parse-function not suitable");
723 REQUIRE (_boundFun (CON::parse),
"unbound recursive syntax");
724 return CON::parse (toParse);
727 template<
typename SPEC>
751 template<
typename SPEC,
typename SEL =
void>
754 template<
typename SPEC>
759 template<
typename SPEC>
762 template<
typename SPEC1,
typename SPEC2>
783 :
public Eval<typename PAR::Result>
806 bool success()
const {
return bool(Syntax::result); }
829 using ConX = PX::Connex;
830 ConX& refConnex = refSyntax;
838 template<
typename SPEC>
839 auto seq (SPEC&& clauseDef);
841 template<
typename SPEC>
842 auto alt (SPEC&& clauseDef);
844 template<
typename SPEC>
845 auto opt (SPEC&& clauseDef);
847 template<
typename SPEC1,
typename SPEC2>
848 auto repeat (
uint min,
uint max, SPEC1&& delimDef, SPEC2&& clauseDef);
850 template<
typename SPEC1,
typename SPEC2>
851 auto repeat (
uint cnt, SPEC1&& delimDef, SPEC2&& clauseDef);
853 template<
typename SPEC1,
typename SPEC2>
854 auto repeat (SPEC1&& delimDef, SPEC2&& clauseDef);
856 template<
typename SPEC>
857 auto repeat (SPEC&& clauseDef);
859 template<
typename SPEC1,
typename SPEC2,
typename SPEC3>
860 auto bracket (SPEC1&& openDef, SPEC2&& closeDef, SPEC3&& bodyDef);
862 template<
typename SPEC>
863 auto bracket (
string bracketSpec, SPEC&& bodyDef);
865 template<
typename SPEC>
868 template<
typename SPEC>
869 auto bracketOpt (
string bracketSpec, SPEC&& bodyDef);
871 template<
typename SPEC>
875 auto bind (FUN&& modelAdapt);
889 template<
typename SPEC>
901 template<
typename SPEC>
917 template<
typename SPEC1,
typename SPEC2>
925 throw err::Invalid{
"Invalid repeat with max ≡ 0 repetitions"};
929 ,
Parser{forward<SPEC1> (delimDef)}
930 ,
Parser{forward<SPEC2> (clauseDef)}));
934 template<
typename SPEC1,
typename SPEC2,
typename =if_acceptableSpecs<SPEC1,SPEC2>>
938 return accept_repeated (cnt,cnt, forward<SPEC1>(delimDef), forward<SPEC2>(clauseDef));
942 template<
typename SPEC1,
typename SPEC2,
typename =if_acceptableSpecs<SPEC1,SPEC2>>
949 template<
typename SPEC>
956 template<
typename SPEC>
963 template<
typename SPEC>
976 template<
typename SPEC1,
typename SPEC2,
typename SPEC3>
982 ,
Parser{forward<SPEC2>(closeDef)}
983 ,
Parser{forward<SPEC3>(bodyDef) }
992 template<
typename SPEC>
996 if (bracketSpec.size() != 2)
997 throw err::Invalid{
"Bracket spec with opening and closing character expected"};
1000 ,
Parser{
"\\"+bracketSpec.substr(1,1)}
1001 ,
Parser{forward<SPEC>(bodyDef) }
1007 template<
typename SPEC>
1015 template<
typename SPEC>
1019 if (bracketSpec.size() != 2)
1020 throw err::Invalid{
"Bracket spec with opening and closing character expected"};
1023 ,
Parser{
"\\"+bracketSpec.substr(1,1)}
1024 ,
Parser{forward<SPEC>(bodyDef) }
1029 template<
typename SPEC>
1054 template<
typename RES>
1072 template<
typename SPEC>
1078 ,
Parser{forward<SPEC> (clauseDef)}));
1094 template<
typename SPEC>
1100 ,
Parser{forward<SPEC> (clauseDef)}));
1110 template<
typename SPEC>
1114 return seq (
accept_opt (forward<SPEC> (clauseDef)));
1123 template<
typename SPEC1,
typename SPEC2>
1128 ,forward<SPEC1>(clauseDef)
1129 ,forward<SPEC2>(clauseDef)));
1133 template<
typename SPEC1,
typename SPEC2>
1138 ,forward<SPEC1>(clauseDef)
1139 ,forward<SPEC2>(clauseDef)));
1143 template<
typename SPEC1,
typename SPEC2>
1148 ,forward<SPEC2>(clauseDef)));
1152 template<
typename SPEC>
1164 template<
typename SPEC1,
typename SPEC2,
typename SPEC3>
1169 ,forward<SPEC2>(closeDef)
1170 ,forward<SPEC3>(bodyDef)));
1174 template<
typename SPEC>
1179 ,forward<SPEC>(bodyDef)));
1183 template<
typename SPEC>
1191 template<
typename SPEC>
1196 ,forward<SPEC>(bodyDef)));
1200 template<
typename SPEC>
1214 ,forward<FUN>(modelAdapt)));
1239 template<
typename...ELMS>
1240 struct tuple_size<
util::parse::SeqModel<ELMS...> >
1241 : tuple_size<typename util::parse::SeqModel<ELMS...>::Tup >
1245 template<
size_t I,
typename...ELMS>
1246 struct tuple_element<I,
util::parse::SeqModel<ELMS...> >
1247 : tuple_element<I, typename util::parse::SeqModel<ELMS...>::Tup >
A Sum Type (variant) to capture values from a branched evaluation.
A Sum Type to hold alternative results from a branched evaluation.
static constexpr auto TOP
Derived specific exceptions within Lumiera's exception hierarchy.
A front-end for using printf-style formatting.
A Parser function to match and accept some syntax.
Eval< Result > operator()(StrView toParse)
Parse-Function operator: test input and yield Eval record.
A Syntax clause with a parser and result state.
auto bracketOpt(string bracketSpec, SPEC &&bodyDef)
auto seq(SPEC &&clauseDef)
===== Syntax clause builder DSL =====
auto repeat(uint min, uint max, SPEC1 &&delimDef, SPEC2 &&clauseDef)
Combinator: extend this Syntax with a further sequenced sub-clause, which in this case accepts a repe...
Syntax & operator=(Syntax< PX > refSyntax)
Syntax && parse(StrView toParse)
Core API : parse against this syntax clause.
auto alt(SPEC &&clauseDef)
Combinator: extend this Syntax by adding an alternative branch.
auto opt(SPEC &&clauseDef)
Combinator: extend this Syntax with a further sequenced sub-clause, which however is only optional an...
auto bindMatch(uint group=0)
auto bracket(SPEC1 &&openDef, SPEC2 &&closeDef, SPEC3 &&bodyDef)
Combinator: extend this Syntax with a further sequenced sub-clause in brackets.
Result && extractResult()
Lumiera error handling (C++ interface).
Metaprogramming tools for detecting and transforming function types.
bool _boundFun(FUN const &fun)
helper to detect return type of a possibly generic λ
auto adaptConnex(CON &&connex, BIND &&modelBinding)
Adapt by applying a result-transforming function after a successful parse.
auto accept_bracketOpt(string bracketSpec, SPEC &&bodyDef)
Start Syntax with a sub-clause, optionally enclosed into brackets.
Connex< std::function< Eval< RES >(StrView)> & > ForwardConnex
auto accept_repeated(uint min, uint max, SPEC1 &&delimDef, SPEC2 &&clauseDef)
Start Syntax clause with a repeated sub-clause, with separator and repetition limit; repetitions ∊ [m...
auto sequenceConnex(C1 &&connex1, C2 &&connex2)
accept sequence of two parse functions
auto accept()
empty Syntax clause to start further definition
auto buildConnex(Nil)
»Null-Connex« which always successfully accepts the empty sequence
auto toStringConnex(CON &&connex, uint part)
auto branchedConnex(C1 &&connex1, C2 &&connex2)
accept either one of two alternative parse functions
auto repeatedConnex(uint min, uint max, C1 &&delimConnex, C2 &&bodyConnex)
repeatedly accept parse-function, optionally delimited.
auto accept_bracket(SPEC1 &&openDef, SPEC2 &&closeDef, SPEC3 &&bodyDef)
Start Syntax with a sub-clause enclosed into a bracketing construct.
lib::meta::enable_if< is_usableSpec< SPEC1 >,lib::meta::enable_if< is_usableSpec< SPEC2 > > > if_acceptableSpecs
Connex< std::function< Eval< RES >(StrView)> > OpaqueConnex
special setup to be pre-declared and then used recursively
auto accept_opt(SPEC &&clauseDef)
start Syntax clause with an optional syntax part
decltype(buildConnex(Nil())) NulP
auto expectResult()
Setup an assignable, recursive Syntax clause, initially empty.
decltype(buildConnex(std::declval< regex >())) Term
lib::meta::enable_if< is_usableSpec< SPEC > > if_acceptableSpec
auto optionalConnex(CNX &&connex)
try to accept parse-function, backtracking if not successful.
auto bracketedConnex(C1 &&openingConnex, C2 &&closingConnex, C3 &&bodyConnex, bool isOptional)
accept some structure enclosed into a bracketing construct.
Marker-Tag for the result from a sub-expression, not to be joined.
Standard case : combinator of two model branches.
size_t leadingWhitespace(STR &&toParse)
std::optional< smatch > matchAtStart(STR &&toParse, regex const ®ex)
Helper algorithm to perform a search but require the match to start at the beginning of the string or...
Convenience wrappers and helpers for dealing with regular expressions.
Sum Model : results from a disjunction of parsing clauses, which are are tested and accepted as alter...
Additionally< EXTRA > addBranch()
static AltModel mark_left(SubSeq &&leftCases)
_Vari< AltModel, CASES... >::Penult Penult
plain value expected for left-branch
AltModel(size_t branchID, INIT &&init)
_Vari< AltModel, CASES... >::Prefix SubSeq
a nested sub-model to extend
static AltModel mark_left(Penult &&leftCase)
static AltModel mark_right(Ultima &&rightCase)
_Vari< AltModel, CASES... >::Ultima Ultima
plain value expected for right-branch
static constexpr size_t N
AltModel< CASES..., EXTRA > Additionally
Building block: parser function definition and connection element.
_Fun< PFun >::Ret::Result Result
Special case Product Model to represent iterative sequence.
Product Model : results from a conjunction of parsing clauses, which are to be accepted in sequence,...
lib::meta::Types< RESULTS... > Seq
SeqModel(X1 &&res1, X2 &&res2)
SeqModel(SeqModel< XS... > &&seq, XX &&extraElm)
static constexpr size_t N
std::tuple< RESULTS... > Tup
decltype(std::declval< FUN >()(std::declval< ARG >())) Ret
Helpers for type detection, type rewriting and metaprogramming.
Metaprogramming support to rebuild and rebind variadic templates.