Library: complete test and documentaton of parsing support
This finishes an ''exercise'' in tool design, which was set off by the requirement to parse the spec-ID of a render node. While generally within the confines of a helper utility for simple use cases, the solution became quite succinct and generic, as it allows to handle arbitrary LL(n) grammars, possibly with recursion.
This commit is contained in:
parent
cdbdf620ca
commit
0a0369a4a5
3 changed files with 385 additions and 98 deletions
|
|
@ -27,6 +27,111 @@
|
|||
** and automatically consuming any leading whitespace. And notably the focus was
|
||||
** _not placed_ on the challenging aspects of parsing — while still allowing a
|
||||
** pathway towards definition of arbitrarily recursive grammars, if so desired.
|
||||
**
|
||||
** ## Functionality
|
||||
** This framework supports the construction of a recursive-descent parser without
|
||||
** underlying lexer. Rather, _terminal expressions_ are delegated to a regular
|
||||
** expression matcher, which allows for some additional leeway, like a negative
|
||||
** match, or using lookahead-assertions. The implementation relies on parser
|
||||
** _functions_ and the _combinator technique_ to combine building blocks — yet
|
||||
** those functions and combinators are wrapped into a syntax-clause builder DSL.
|
||||
** Each parse yields a result, depending on the structure of the parse-function.
|
||||
** The base building block, a parser to accept a regular expression, will yield
|
||||
** the C++ matcher object as result — and thus essentially some pointers into
|
||||
** the original sequence, which has to be passed in as C++ string_view.
|
||||
**
|
||||
** An essential concept of this parsing support framework is that each parser
|
||||
** can be decorated by a _model transformation functor,_ which gets the result
|
||||
** of the wrapped parser and can return _any arbitrary value object._ In essence,
|
||||
** this framework does not provide the notion of an _abstract syntax tree_ — yet
|
||||
** the user is free to build a custom syntax tree, relying on these model-bindings.
|
||||
**
|
||||
** \par Syntax building blocks
|
||||
** - `accept(SPEC)` builds a clause to accept anything the given SPEC for
|
||||
** a parser function would accept and to yield its return model.
|
||||
** The `SPEC` argument might be...
|
||||
** + a string describing regular expression syntax
|
||||
** + a C++ regexp object
|
||||
** + any hand-written functor `string_view ⟼ model`
|
||||
** + an existing syntax clause (either by RValue or LValue)
|
||||
** - `accept_opt` builds a clause to optionally accept in accordance
|
||||
** to the given definition; if no match is found, parsing backtracks.
|
||||
** - `accept_repeated` builds a clause to accept a repetition of the
|
||||
** structure accepted by its argument, optionally with an explicit delimiter
|
||||
** and possibly with a limited number of instances. The result values are
|
||||
** obviously all from the same type and will be collected into a IterModel,
|
||||
** which essentially is a std::vector<RES> (note: heap storage!).
|
||||
** - `accept_bracket` builds a clause to accept the structure of the
|
||||
** given argument, but enclosed in parentheses, or an explicitly defined
|
||||
** pair of delimiters. Variants are provided to accept optional bracketing.
|
||||
** - `<syntax>.seq(SPEC)` extends a given syntax clause to accept the structure
|
||||
** described by the SPEC _after_ the structure already described by the syntax.
|
||||
** Both parts must succeed for the parse to be successful. The result value
|
||||
** is packaged into a parse::SeqModel, which essentially is a tuple; when
|
||||
** attaching several .seq() specifications, it can become a N-ary tuple.
|
||||
** - `<syntax>.alt(SPEC)` adds an _alternative branch_ to the existing syntax.
|
||||
** Either part alone is sufficient for a successful parse. First the existing
|
||||
** branch(es) are tried, and only if those do not succeed, backtracking is
|
||||
** performed and then the alternative branch is tried. Once some match is
|
||||
** found, further branches will _not be attempted._ (short-circuit).
|
||||
** Thus there is _always one_ result model, is placed into an AltModel,
|
||||
** which is a _variant data type_ with a common inline result buffer.
|
||||
** The _selector field_ must be checked to find out which branch of the
|
||||
** syntax succeeded, and then the result must be handled with its appropriate
|
||||
** type, because the various branches can possibly yield entirely different
|
||||
** result value types.
|
||||
** - `<syntax>.repeat()` _sequentially adds_ a repeated clause be accepted
|
||||
** _after_ what the existing syntax accepts. The result is thus a SeqModel.
|
||||
** - `<syntax>.bracket()` _sequentially adds_ a bracketing clause to be
|
||||
** accepted _after_ parsing with the existing syntax. Again, the result
|
||||
** is a SeqModel, with the result-model from the repetition in the last
|
||||
** tuple element. The repetition itself yields an IterModel.
|
||||
** - `<syntax>.bind(FUN)` is a postfix-operator and decorates the existing
|
||||
** syntax with a result-binding functor `FUN`: The syntax's result value
|
||||
** is passed into this functor and whatever this functor returns will
|
||||
** become the result value of the compound.
|
||||
** - `<syntax>.bindMatch(n)`: a convenience shortcut to bind to the complete
|
||||
** input substring accepted by the underlying parser, or (when directly
|
||||
** applied to a reg-exp terminal) it can also extract a match-sub-group.
|
||||
** The result value of the resulting syntax clause will thus be a string.
|
||||
**
|
||||
** ### Recursion
|
||||
** A _recursive syntax definition_ is what unleashes the parsing technique's
|
||||
** full strength; but recursive grammars can be challenging to master at times
|
||||
** and may in fact lead to deadlock due to unlimited recursion. Since this
|
||||
** framework is focused on ease of use in simple situations, recursion is
|
||||
** considered an advanced usage and thus supported in a way that requires
|
||||
** some preparation and help by the user. In essence...
|
||||
** - a syntax clause to be referred recursively _must be pre-declared_
|
||||
** - this pre-declaration gives it a known, fixed result type and will
|
||||
** internally use a `std::function` as parse function, initially empty.
|
||||
** - later the full syntax must be defined, and supplemented with a binding
|
||||
** to yield precisely the result-model type as pre-declared
|
||||
** - finally this definition is _assigned_ to the pre-declared syntax object.
|
||||
** One point to note is that internally a _reference_ to the pre-declared
|
||||
** `std::function` is stored — implying that the pre-declared syntax object
|
||||
** must **remain in scope and can not be moved**. Other than requiring
|
||||
** such a special setup, recursive syntax can be used without limits.
|
||||
**
|
||||
** ## Structure
|
||||
** The util::parse::Syntax object is what the user handles and interacts with.
|
||||
** It both holds a result record of type util::parse::Eval, and a parser object
|
||||
** of type util::parse::Parser, while also acting as a move-style DSL builder.
|
||||
** Here, _move-style_ implies that invoking a DSL extension operator will
|
||||
** _move the embedded parser function_ into a new Syntax object with different
|
||||
** result type. However, when starting with some of the top-level function-style
|
||||
** builders, a given syntax object will be copied. This is important to keep
|
||||
** in mind when building complex expressions. Another point worth mentioning
|
||||
** is that the basic parse relies on std::string_view, which implies that the
|
||||
** original input sequence must remain valid until the parse result is built.
|
||||
**
|
||||
** At the heart of the combinator mechanics is the class util::part::Connex,
|
||||
** which is essentially a parser function with additional configuration, and
|
||||
** can be passed to one of the _combinator functions_ `buildXXXConnex(...)`.
|
||||
** The construction of compound model results relies on a set of overloaded
|
||||
** `_Join` templates, which specify the way how models can be combined and
|
||||
** sequences can be extended.
|
||||
**@see parse-test.cpp
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -41,7 +146,6 @@
|
|||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
#include "lib/regex.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"/////////TODO
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
|
@ -266,7 +370,7 @@ namespace util {
|
|||
else
|
||||
{ // defensive fall-back: ignore model, return accepted input part
|
||||
size_t pre = leadingWhitespace (toParse);
|
||||
return {string{toParse.substr (pre, eval.consumed)}
|
||||
return {string{toParse.substr (pre, eval.consumed - pre)}
|
||||
,eval.consumed
|
||||
};
|
||||
}
|
||||
|
|
@ -377,9 +481,7 @@ namespace util {
|
|||
/** Marker-Tag for the result from a sub-expression, not to be joined */
|
||||
template<typename RES>
|
||||
struct SubModel
|
||||
{
|
||||
RES model;
|
||||
};
|
||||
{ /* for metaprogramming only */ };
|
||||
|
||||
|
||||
/** Standard case : combinator of two model branches */
|
||||
|
|
|
|||
|
|
@ -19,15 +19,10 @@
|
|||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/parse.hpp"
|
||||
//#include "lib/format-util.hpp"
|
||||
#include "lib/meta/tuple-helper.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"//////////////////TODO
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
//#include <vector>
|
||||
//#include <memory>
|
||||
#include "lib/parse.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace util {
|
||||
|
|
@ -38,35 +33,15 @@ namespace test {
|
|||
using lib::meta::typeSymbol;
|
||||
using lib::meta::is_Tuple;
|
||||
using std::decay_t;
|
||||
using std::vector;
|
||||
using std::get;
|
||||
// using util::join;
|
||||
// using util::isnil;
|
||||
// using std::vector;
|
||||
// using std::shared_ptr;
|
||||
// using std::make_shared;
|
||||
|
||||
// using LERR_(ITER_EXHAUST);
|
||||
// using LERR_(INDEX_BOUNDS);
|
||||
|
||||
|
||||
namespace { // test fixture
|
||||
|
||||
// const uint NUM_ELMS = 10;
|
||||
|
||||
// using Numz = vector<uint>;
|
||||
|
||||
} // (END)fixture
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************//**
|
||||
* @test verify helpers and shortcuts for simple recursive descent parsing
|
||||
/****************************************************//**
|
||||
* @test verify support for recursive descent parsing
|
||||
* of structured data and specifications.
|
||||
*
|
||||
* @see parse.hpp
|
||||
* @see proc-node.cpp "usage example"
|
||||
*/
|
||||
|
|
@ -77,6 +52,7 @@ namespace test {
|
|||
run (Arg)
|
||||
{
|
||||
simpleUsage();
|
||||
|
||||
acceptTerminal();
|
||||
acceptSequential();
|
||||
acceptAlternatives();
|
||||
|
|
@ -90,13 +66,32 @@ namespace test {
|
|||
}
|
||||
|
||||
|
||||
/** @test TODO just blah. */
|
||||
/** @test demonstrate parsing a function-with-arguments structure. */
|
||||
void
|
||||
simpleUsage ()
|
||||
{
|
||||
using Model = std::pair<string, vector<string>>;
|
||||
|
||||
auto word = accept("\\w+").bindMatch();
|
||||
auto term = accept(word)
|
||||
.bracket (accept_repeated(",", word))
|
||||
.bind([](auto res){ return Model{get<0>(res),get<1>(res)}; });
|
||||
|
||||
CHECK (not term.hasResult());
|
||||
|
||||
term.parse("great (hypertrophy, confusion, deception, profit)");
|
||||
CHECK (term.success());
|
||||
Model model = term.getResult();
|
||||
CHECK (model.first == "great");
|
||||
CHECK (model.second[0] == "hypertrophy");
|
||||
CHECK (model.second[1] == "confusion" );
|
||||
CHECK (model.second[2] == "deception" );
|
||||
CHECK (model.second[3] == "profit" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** @test define a terminal symbol to match by parse. */
|
||||
void
|
||||
acceptTerminal()
|
||||
|
|
@ -106,7 +101,7 @@ namespace test {
|
|||
string toParse{"hello vile world of power"};
|
||||
auto eval = parse (toParse);
|
||||
CHECK (eval.result);
|
||||
smatch res = *eval.result; // ◁——————————— the »result model« of a terminal parse is the RegExp-Matcher
|
||||
smatch res = *eval.result; // ◁——————————————————————— »result model« of a terminal parse is the RegExp-Matcher
|
||||
CHECK (res.ready() and not res.empty());
|
||||
CHECK (res.size() == "2"_expect );
|
||||
CHECK (res.position() == "0"_expect );
|
||||
|
|
@ -133,7 +128,7 @@ namespace test {
|
|||
|
||||
// Going full circle: extract Parser definition from syntax
|
||||
auto parse2 = Parser{syntax2};
|
||||
CHECK (eval.result->str(1) == "vile");
|
||||
CHECK (eval.result->str(1) == "vile"); // leftover value
|
||||
eval = parse2 (toParse);
|
||||
CHECK (not eval.result);
|
||||
eval = parse2 (bye);
|
||||
|
|
@ -145,7 +140,7 @@ namespace test {
|
|||
* - first demonstrate explicitly how the consecutive parsing works
|
||||
* and how both models are combined into a product model (tuple)
|
||||
* - demonstrate how leading whitespace is skipped automatically
|
||||
* - then perform the same parse with a Syntax clause build with
|
||||
* - then perform the same parse with a Syntax clause, built by
|
||||
* the `seq()` builder-DSL
|
||||
* - extend this Syntax by adding a further sequential clause.
|
||||
*/
|
||||
|
|
@ -198,8 +193,8 @@ namespace test {
|
|||
CHECK (not term2.parse(" old ").result);
|
||||
|
||||
|
||||
//___________________________________________________
|
||||
// DSL parse clause builder: a sequence of terminals...
|
||||
//____________________________________________________
|
||||
// DSL syntax clause builder: a sequence of terminals...
|
||||
auto syntax = accept("hello").seq("world");
|
||||
|
||||
// Perform the same parse as demonstrated above....
|
||||
|
|
@ -214,8 +209,9 @@ namespace test {
|
|||
|
||||
|
||||
// can build extended clause from existing one
|
||||
auto syntax2 = syntax.seq("trade");
|
||||
auto syntax2 = accept(syntax).seq("trade"); // Warning: seq() moves the parse function (but accept() has created a copy)
|
||||
CHECK (not syntax2.hasResult());
|
||||
CHECK ( syntax.hasResult()); // ...so the syntax2 is indeed an independent instance now
|
||||
syntax2.parse(s2);
|
||||
CHECK (not syntax2.success());
|
||||
syntax2.parse(s3);
|
||||
|
|
@ -228,11 +224,12 @@ namespace test {
|
|||
|
||||
|
||||
|
||||
/** @test define alternative syntax structures to match by parse.
|
||||
/** @test define alternative syntax clauses to match by parse.
|
||||
* - first demonstrate how a model with alternative branches can be
|
||||
* populated and gradually extended while searching for a match.
|
||||
* - then show explicitly the logic to check and select branches
|
||||
* and construct the corresponding sum-model (variant)
|
||||
* - finally demonstrate equivalent behaviour using the DSL
|
||||
*/
|
||||
void
|
||||
acceptAlternatives()
|
||||
|
|
@ -340,7 +337,7 @@ namespace test {
|
|||
CHECK (altModel.get<0>().str() == "brazen");
|
||||
|
||||
// can build extended clause from existing one
|
||||
auto syntax2 = syntax.alt("smarmy (\\w+)");
|
||||
auto syntax2 = accept(syntax).alt("smarmy (\\w+)");
|
||||
CHECK (not syntax2.hasResult());
|
||||
syntax2.parse(s1);
|
||||
CHECK (not syntax2.success());
|
||||
|
|
@ -370,10 +367,10 @@ namespace test {
|
|||
{ //_______________________________________________
|
||||
// Demonstration: how repetitive sequence works....
|
||||
auto sep = buildConnex (",");
|
||||
auto term = buildConnex ("\\w+");
|
||||
auto word = buildConnex ("\\w+");
|
||||
auto parseSeq = [&](StrView toParse)
|
||||
{
|
||||
using Res = decltype(term)::Result;
|
||||
using Res = decltype(word)::Result;
|
||||
using IterResult = std::vector<Res>;
|
||||
using IterEval = Eval<IterResult>;
|
||||
uint consumed{0};
|
||||
|
|
@ -389,7 +386,7 @@ namespace test {
|
|||
break;
|
||||
offset += delim.consumed;
|
||||
}
|
||||
auto eval = term.parse (toParse.substr(offset));
|
||||
auto eval = word.parse (toParse.substr(offset));
|
||||
if (not eval.result)
|
||||
break;
|
||||
offset += eval.consumed;
|
||||
|
|
@ -424,7 +421,7 @@ namespace test {
|
|||
|
||||
//______________________________________________
|
||||
// DSL parse clause builder: iterative sequence...
|
||||
auto syntax1 = accept_repeated(",", term);
|
||||
auto syntax1 = accept_repeated(",", word);
|
||||
|
||||
// Perform the same parse as demonstrated above....
|
||||
CHECK (not syntax1.hasResult());
|
||||
|
|
@ -442,8 +439,8 @@ namespace test {
|
|||
CHECK (res1[1].str() == "extort" );
|
||||
CHECK (res1[2].str() == "profit" );
|
||||
|
||||
auto syntax2 = accept_repeated(1,2,",", term);
|
||||
auto syntax3 = accept_repeated( 4,",", term);
|
||||
auto syntax2 = accept_repeated(1,2,",", word);
|
||||
auto syntax3 = accept_repeated( 4,",", word);
|
||||
syntax2.parse(s2);
|
||||
syntax3.parse(s2);
|
||||
CHECK ( syntax2);
|
||||
|
|
@ -460,7 +457,7 @@ namespace test {
|
|||
CHECK (syntax3.getResult()[2].str() == "profit" );
|
||||
CHECK (syntax3.getResult()[3].str() == "dump" );
|
||||
|
||||
auto syntax4 = accept_repeated(term);
|
||||
auto syntax4 = accept_repeated(word);
|
||||
syntax4.parse(s1);
|
||||
CHECK (syntax4.success());
|
||||
CHECK (syntax4.getResult().size() == 2);
|
||||
|
|
@ -743,6 +740,7 @@ namespace test {
|
|||
.alt(quote)
|
||||
.alt(paren));
|
||||
|
||||
// abbreviation for the test...
|
||||
auto apply = [](auto& syntax)
|
||||
{ return [&](auto const& str)
|
||||
{ return accept(syntax).bindMatch()
|
||||
|
|
@ -751,25 +749,25 @@ namespace test {
|
|||
};
|
||||
};
|
||||
|
||||
SHOW_EXPR(apply(content)("prey .. haul .. loot"))
|
||||
SHOW_EXPR(apply(content)("prey .. haul ,. loot"))
|
||||
SHOW_EXPR(apply(content)("prey .( haul ,. loot"))
|
||||
CHECK (apply(content)("prey .. haul .. loot") == "prey .. haul .. loot"_expect );
|
||||
CHECK (apply(content)("prey .. haul ,. loot") == "prey .. haul "_expect );
|
||||
CHECK (apply(content)("prey .( haul ,. loot") == "prey ."_expect );
|
||||
|
||||
SHOW_EXPR(apply(quote)("\"prey .( haul ,\"loot"))
|
||||
SHOW_EXPR(apply(quote)("\"prey \\ haul ,\"loot"))
|
||||
SHOW_EXPR(apply(quote)("\"prey\\\"haul ,\"loot"))
|
||||
CHECK (apply(quote)("\"prey .( haul ,\"loot") == "\"prey .( haul ,\""_expect );
|
||||
CHECK (apply(quote)("\"prey \\ haul ,\"loot") == "\"prey \\ haul ,\""_expect );
|
||||
CHECK (apply(quote)("\"prey\\\"haul ,\"loot") == "\"prey\\\"haul ,\""_expect );
|
||||
|
||||
SHOW_EXPR(apply(paren)("(prey) .. haul .. loot"))
|
||||
SHOW_EXPR(apply(paren)("(prey .. haul .. loot)"))
|
||||
SHOW_EXPR(apply(paren)("(prey(..(haul)..)loot)"))
|
||||
SHOW_EXPR(apply(paren)("(prey \" haul)\" loot)"))
|
||||
SHOW_EXPR(apply(paren)("(prey\\( haul)\" loot)"))
|
||||
CHECK (apply(paren)("(prey) .. haul .. loot") == "(prey)"_expect );
|
||||
CHECK (apply(paren)("(prey .. haul .. loot)") == "(prey .. haul .. loot)"_expect );
|
||||
CHECK (apply(paren)("(prey(..(haul)..)loot)") == "(prey(..(haul)..)loot)"_expect );
|
||||
CHECK (apply(paren)("(prey \" haul)\" loot)") == "(prey \" haul)\" loot)"_expect );
|
||||
CHECK (apply(paren)("(prey\\( haul)\" loot)") == "(prey\\( haul)"_expect );
|
||||
|
||||
SHOW_EXPR(apply(spec)("\"prey .( haul ,\"loot!"))
|
||||
SHOW_EXPR(apply(spec)("\"prey .( haul \",loot!"))
|
||||
SHOW_EXPR(apply(spec)(" prey .( haul \",loot!"))
|
||||
SHOW_EXPR(apply(spec)(" prey .( haul )\"loot!"))
|
||||
SHOW_EXPR(apply(spec)(" (prey\\( haul }, loot)"))
|
||||
CHECK (apply(spec)("\"prey .( haul ,\"loot!") == "\"prey .( haul ,\"loot!"_expect);
|
||||
CHECK (apply(spec)("\"prey .( haul \",loot!") == "\"prey .( haul \""_expect );
|
||||
CHECK (apply(spec)(" prey .( haul \",loot!") == "prey ."_expect );
|
||||
CHECK (apply(spec)(" prey .( haul,)\"loot!") == "prey .( haul,)"_expect );
|
||||
CHECK (apply(spec)(" (prey\\( haul }, loot)") == "(prey\\( haul }, loot)"_expect );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -55169,7 +55169,8 @@
|
|||
</node>
|
||||
<node CREATED="1736882670002" ID="ID_1282038470" MODIFIED="1736883801040" TEXT="schlankes Parser-Combinator-Framework">
|
||||
<linktarget COLOR="#586e82" DESTINATION="ID_1282038470" ENDARROW="Default" ENDINCLINATION="-1550;3855;" ID="Arrow_ID_950785657" SOURCE="ID_1113355653" STARTARROW="None" STARTINCLINATION="1131;56;"/>
|
||||
<node CREATED="1736718095868" ID="ID_149635951" MODIFIED="1736718100054" TEXT="Skizze">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#306476" CREATED="1736718095868" ID="ID_149635951" MODIFIED="1737603564463" TEXT="Skizze">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1736718101981" ID="ID_749637806" MODIFIED="1736718178019" TEXT="Parser">
|
||||
<node CREATED="1736718185911" ID="ID_869386255" MODIFIED="1736718261272" TEXT="StrView ⟼ Eval<RES>"/>
|
||||
<node CREATED="1736718295056" ID="ID_1924298162" MODIFIED="1736718391443" TEXT="construct">
|
||||
|
|
@ -55277,9 +55278,11 @@
|
|||
<node CREATED="1736728565818" ID="ID_787144515" MODIFIED="1736728580729" TEXT="PAR : Parser-Typ konfiguriert die Syntax"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1736811553465" ID="ID_758725308" MODIFIED="1736897374205" TEXT="Ausarbeitung einer Implementierung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1736811562712" ID="ID_501249017" MODIFIED="1736811566252" TEXT="Entscheidungen">
|
||||
<node COLOR="#338800" CREATED="1736811553465" ID="ID_758725308" MODIFIED="1738186737822" TEXT="Ausarbeitung einer Implementierung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1736811562712" ID="ID_501249017" MODIFIED="1738186387349" TEXT="Entscheidungen">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="list"/>
|
||||
<node CREATED="1736817250352" ID="ID_401051695" MODIFIED="1736817482304" TEXT="vom pragmatischen Nutzen her aufbauen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -55333,7 +55336,8 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1736885232130" ID="ID_611424900" MODIFIED="1736885246544" TEXT="Stateful aber nicht zuweisbar">
|
||||
<node CREATED="1736885232130" ID="ID_611424900" MODIFIED="1738186097643" TEXT="Stateful und zuweisbar">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1736885268189" ID="ID_836482464" MODIFIED="1736885685286" TEXT="stateful erscheint sinnvoll wegen der Builder-Notation">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
|
|
@ -55344,12 +55348,22 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1736885690901" ID="ID_728944641" MODIFIED="1736885913639" TEXT="Kann nicht zuweisbar sein, aufgrund der λ-inline-Storage">
|
||||
<node CREATED="1736885690901" ID="ID_728944641" MODIFIED="1738186084054" TEXT="Kann nicht immer zuweisbar sein, aufgrund der λ-inline-Storage">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Wenn man schon ein zustandsbehaftetes Objekt akzeptiert, könnte auch Zuweisbarkeit bequem sein (man muß dann ja ohnehin aufpassen). Allerdings steht das im Konflikt mit dem Ansatz einer fein-granularen Typisierung, welche die Modell-Struktur abbildet. Und die Entscheidung, die recursive-descent-Struktur als parse-λ einzubetten, verbietet explizit die Zuweisbarkeit, denn man kann (und darf) nicht wissen, was in der Closure steckt
|
||||
Wenn man schon ein zustandsbehaftetes Objekt akzeptiert, könnte auch Zuweisbarkeit bequem sein (man muß dann ja ohnehin aufpassen). Allerdings steht das im Konflikt mit dem Ansatz einer fein-granularen Typisierung, welche die Modell-Struktur abbildet. Und die Entscheidung, die recursive-descent-Struktur als parse-λ einzubetten, verhindert in den meisten Fällen die Zuweisbarkeit, denn man kann (und darf) nicht wissen, was in der Closure steckt
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1738186099863" ID="ID_1323355794" MODIFIED="1738186211338" TEXT="zur Unterstützung rekursiver Syntax wird Zuweisung aber benötigt">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
....in der weiteren Entwicklung zeigte sich, daß der Ansatz mit den direkt aufgegriffenen λ-Typen seine Grenzen findet, sobald die Syntax-Klauseln rekursiv werden; in diesem Fall müßen wir explizit die Typisierung <i>abschneiden.</i> Das ist ein Kompromiß, den ich für angemessen halte
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
|
|
@ -55404,10 +55418,71 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1738185613258" ID="ID_1951563893" MODIFIED="1738185902080" TEXT="Model-Komposition folgt automatisch der Syntax-Struktur (Metaprogramming)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Das ist eine grundsätzliche Entscheidung, die direkt aus den explizit aufgegriffenen und eingebundenen λ-Typen folgt:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
dieses Framework baut selber <b>keinen Syntaxbaum auf</b>
|
||||
</li>
|
||||
<li>
|
||||
dafür aber verwenden wir Metaprogrammierung, um aus den Builder-DSL-Aufrufen einen strukturierten Model-Term aufzubauen, der dem Aufbau der Syntax folgt
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#387ba0" DESTINATION="ID_364383845" ENDARROW="Default" ENDINCLINATION="188;-1058;" ID="Arrow_ID_1232592082" STARTARROW="None" STARTINCLINATION="1081;40;"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1736811967713" ID="ID_1645773137" MODIFIED="1736897400600" TEXT="Aufbau">
|
||||
<node CREATED="1738185903843" ID="ID_780195440" MODIFIED="1738186010535" TEXT="per explizitem binding-λ läßt sich jedoch das Model jederzeit reduzieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...man ist also nicht in die komplexen, verschachtelten Strukturen hineingezwungen, sondern kann an strategisch günstiger Stelle in einen eigenen Model-Typ übersetzen; für die unterstützung rekursiver Syntax-Klauseln erweist sich das sogar als essentiell
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1738186239565" ID="ID_1545863351" MODIFIED="1738186377434" TEXT="Einstiegspunkte in Funktions-Notation bieten (vorsicht mit Postfix-Operatoren)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Aus Sicht der technischen Konstruktion erschien es mir erst sehr naheliegend, die DSL-Syntax weitgehend auf Postfix-Operatoren aufzubauen. Das erwies sich als Trugschluß, denn solche Konstrukte sind in der praktischen Anwendung schwer zu durchschauen. Daher habe ich die Präferenzen unterwegs geändert und die DSL so umstrukturiert, daß sie eine Reihe freier Funktionen als Einstiegspunkt bietet, und diese freien Funktionen auch dazu dienen sollen, verschachtelte Sub-Syntax-Klauseln einzuleiten
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1738186420476" ID="ID_1410288950" MODIFIED="1738186727976" TEXT="Rekursion ermöglichen durch pre-deklarierte Klauseln und Bindings">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Rekursion ist ein essentielles Element jeden echten Parsers; sie ist aber auch komplex (und potentiell nicht-terminierend). Daher sollen die meisten Anwendungsfälle durch vorgefertigte Syntax-Elemente (Repetition und Klammerung) abgefangen werden. Für die sonstigen Fälle verlangen wir vom Benutzer etwas Vorarbeit: der Model-Result-Type muß in diesem Fall durch ein Binding <i>reduziert werden</i>, so daß das Ergebnis einer rekursiven Referenz bereits feststeht. Damit konnte an der Stelle (mithilfe von std::function) eine elegante Lösung gefunden werden, die nach außen nahezu unsichtbar bleibt:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
der Benutzer muß rekursiv zu referenzierende Klauseln vordefinieren, mit angegebenem Ergebnistyp
|
||||
</li>
|
||||
<li>
|
||||
später muß in der Definition der Klausel am Ende ein Model-Binding stehen, das <i>genau diesen Result-Typ liefert</i>
|
||||
</li>
|
||||
<li>
|
||||
schließlich wird diese Definition dem pre-deklarierten Syntax-Objekt <b>zugewiesen</b>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#dbf0b6" COLOR="#006399" CREATED="1736811967713" ID="ID_1645773137" MODIFIED="1738185134450" TEXT="Aufbau">
|
||||
<icon BUILTIN="edit"/>
|
||||
<node CREATED="1736811972979" ID="ID_1413698396" MODIFIED="1736812166866" TEXT="Policy-Base als Struktur-Konfiguration">
|
||||
<node COLOR="#435e98" CREATED="1736811972979" ID="ID_1413698396" MODIFIED="1738185498885" TEXT="Policy-Base als Struktur-Konfiguration">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1736812168622" ID="ID_596543939" MODIFIED="1736812184719" TEXT="Parser erbt die Funktor-Eigenschaft von der Policy-Base"/>
|
||||
<node CREATED="1736815274234" ID="ID_1286749463" MODIFIED="1736815303733">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -55420,7 +55495,8 @@
|
|||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1736875251595" ID="ID_193269102" MODIFIED="1736875261198" TEXT="Regexp-search">
|
||||
<node COLOR="#338800" CREATED="1736875251595" ID="ID_193269102" MODIFIED="1738185491685" TEXT="Regexp-search">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1736875265103" ID="ID_205680289" MODIFIED="1736875271589" TEXT="oops ... gar nicht so einfach"/>
|
||||
<node CREATED="1736875272991" ID="ID_460559047" MODIFIED="1736875300935" TEXT="deshalb verwende ich fast überall meinen RegexSearchIterator"/>
|
||||
<node CREATED="1736875303467" ID="ID_376628405" MODIFIED="1736875334408" TEXT="Problem: Match-Verankerung am Anfang">
|
||||
|
|
@ -55457,7 +55533,7 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1736896942694" ID="ID_50956958" MODIFIED="1737649641200" TEXT="Kreis schließen: Parser wieder aus Syntax bauen">
|
||||
<node COLOR="#435e98" CREATED="1736896942694" ID="ID_50956958" MODIFIED="1738185461447" TEXT="Kreis schließen: Parser wieder aus Syntax bauen">
|
||||
<linktarget COLOR="#587bde" DESTINATION="ID_50956958" ENDARROW="Default" ENDINCLINATION="-792;1631;" ID="Arrow_ID_1971370194" SOURCE="ID_950065344" STARTARROW="None" STARTINCLINATION="-1469;98;"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1736896960412" ID="ID_281482378" MODIFIED="1736896967137" TEXT="will nicht recht funktionieren">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
|
|
@ -55490,7 +55566,8 @@
|
|||
<node CREATED="1737656610177" ID="ID_1186453687" MODIFIED="1737656620354" TEXT="Syntax muß conversion-Operator bieten"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1736897170512" ID="ID_28739070" MODIFIED="1736897191019" TEXT="Fazit: muß sinnvollerweise direkt aus Syntax heraus angestoßen werden">
|
||||
<node COLOR="#435e98" CREATED="1736897170512" ID="ID_28739070" MODIFIED="1738185475861" TEXT="Fazit: muß sinnvollerweise direkt aus Syntax heraus angestoßen werden">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1736897207538" ID="ID_953670876" MODIFIED="1736897215717" TEXT="das ist wohl akzeptabel"/>
|
||||
<node CREATED="1736897216258" ID="ID_1489413453" MODIFIED="1736897231402" TEXT="wirklich gebraucht wird es nur als Basis für die Combinator-Implementierung"/>
|
||||
<node CREATED="1736897235991" ID="ID_444935473" MODIFIED="1736897247114" TEXT="diese könnte man aber auch in buildConnex verlagern">
|
||||
|
|
@ -55606,7 +55683,7 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1736948672141" ID="ID_134095537" MODIFIED="1736948681272" TEXT="könnte potentiell unerwünscht sein">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1736948672141" ID="ID_134095537" MODIFIED="1738185414315" TEXT="könnte potentiell unerwünscht sein">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1736948788817" ID="ID_239959705" MODIFIED="1736949060127" TEXT="Beispiel: geklammerte Sequenz in der Syntax, weitere Sequenz">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -55630,7 +55707,7 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#380f69" CREATED="1736968942247" ID="ID_917376104" MODIFIED="1737511498798" TEXT="muß Anfangswert der Fold-Sequenz explizit konstruieren">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#380f69" CREATED="1736968942247" FOLDED="true" ID="ID_917376104" MODIFIED="1737511498798" TEXT="muß Anfangswert der Fold-Sequenz explizit konstruieren">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1736971224510" ID="ID_1155045892" MODIFIED="1736972005211" TEXT="das kann aber durch Binding-Komposition realisiert werden">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -55797,8 +55874,9 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1736988419593" ID="ID_364383845" MODIFIED="1737511653707" TEXT="Pattern-Match und Spezialfall-Implementierung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1736988419593" ID="ID_364383845" MODIFIED="1738185722929" TEXT="Pattern-Match und Spezialfall-Implementierung">
|
||||
<linktarget COLOR="#387ba0" DESTINATION="ID_364383845" ENDARROW="Default" ENDINCLINATION="188;-1058;" ID="Arrow_ID_1232592082" SOURCE="ID_1951563893" STARTARROW="None" STARTINCLINATION="1081;40;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1736988439351" ID="ID_396611819" MODIFIED="1736988490982" TEXT="verwende ein explizit definiertes Tag: Sub<X>"/>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1736988542489" ID="ID_1635129166" MODIFIED="1737234629319" TEXT="Model-Join extrahieren">
|
||||
<arrowlink COLOR="#465acd" DESTINATION="ID_226754618" ENDARROW="Default" ENDINCLINATION="-418;52;" ID="Arrow_ID_1636406845" STARTARROW="None" STARTINCLINATION="-11;79;"/>
|
||||
|
|
@ -55869,8 +55947,8 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1737048069726" ID="ID_129104167" MODIFIED="1737048085836" TEXT="Fall-Differenzierung der _Join-Konstruktoren">
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#4e1da1" CREATED="1737048069726" ID="ID_129104167" MODIFIED="1738185172292" TEXT="Fall-Differenzierung der _Join-Konstruktoren">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1737234497746" ID="ID_936287985" MODIFIED="1737234549166" TEXT="Sequence">
|
||||
<icon BUILTIN="info"/>
|
||||
<node COLOR="#435e98" CREATED="1737234502793" ID="ID_1552148571" MODIFIED="1737234536557" TEXT="akzeptiere zwei Werte ⟶ Paar"/>
|
||||
|
|
@ -55882,6 +55960,10 @@
|
|||
<node COLOR="#435e98" CREATED="1737511691172" ID="ID_1192322879" MODIFIED="1737511740655" TEXT="akzeptiere AltModel + Wert ⟶ neuen Fall für «Wert» zum AltModel hinzufügen"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c3c9ac" COLOR="#338800" CREATED="1738185189251" HGAP="-3" ID="ID_1949817857" MODIFIED="1738185220941" TEXT="das genügt um das Thema in den Griff zu bekommen" VSHIFT="7">
|
||||
<font NAME="SansSerif" SIZE="10"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1737048133742" ID="ID_1028852897" MODIFIED="1737511601637" TEXT="Einbindung in die DSL-Notation (class Syntax)">
|
||||
|
|
@ -56023,7 +56105,7 @@
|
|||
<node COLOR="#338800" CREATED="1737511832794" ID="ID_209338146" MODIFIED="1737511947153" TEXT="Steuerung der Model-Komposition lösen">
|
||||
<arrowlink COLOR="#579bd2" DESTINATION="ID_226754618" ENDARROW="Default" ENDINCLINATION="6;427;" ID="Arrow_ID_220186183" STARTARROW="None" STARTINCLINATION="1852;-83;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1737511902291" HGAP="21" ID="ID_1061539705" MODIFIED="1737512327118" TEXT="die Fälle werden übersetzt in Template-Spezialisierungen" VSHIFT="19"/>
|
||||
<node COLOR="#435e98" CREATED="1737511902291" HGAP="22" ID="ID_1061539705" MODIFIED="1737512327118" TEXT="die Fälle werden übersetzt in Template-Spezialisierungen" VSHIFT="36"/>
|
||||
<node COLOR="#435e98" CREATED="1737511916591" ID="ID_1159668962" MODIFIED="1737511950227" TEXT="zusätzliches Marker-Template um verschachtelte Sub-Ausdrücke auszuklammern"/>
|
||||
<node COLOR="#438798" CREATED="1737512313284" HGAP="21" ID="ID_1608529418" LINK="#ID_1402725802" MODIFIED="1737512347700" TEXT="(partielle) Typsicherheit auch beim Variant-Model">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1737512357123" ID="ID_1348106042" MODIFIED="1737512388092" TEXT="Aber: im Model-Binding muß man die Selektoren korrekt verwenden"/>
|
||||
|
|
@ -57237,6 +57319,20 @@
|
|||
<node CREATED="1737817647567" ID="ID_1641437634" MODIFIED="1737817658826" TEXT="bindMatch() könnte noch mehr tun"/>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1737849826967" ID="ID_1650492122" MODIFIED="1737849845902" TEXT="erst mal weiter sehen wie sehr das in der Praxis hindert">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1738184826030" ID="ID_1210934055" MODIFIED="1738184962313" TEXT="denke nämlich: mit konsistentem Schema nicht so schlimm">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...rein nach Bauchgefühl dürfte das in der Praxis dann doch nicht so schlimm werden, sofern man konsistent jede Klausel auch mit einem Binding ausstattet, und die Ergebnistypen systematisch aufbaut. Schließlich ist <i>das ja auch die Aufgabe schlechthin beim Parsen</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#8f8aac" DESTINATION="ID_1009402167" ENDARROW="Default" ENDINCLINATION="545;-25;" ID="Arrow_ID_1645190934" STARTARROW="None" STARTINCLINATION="798;36;"/>
|
||||
</node>
|
||||
<node CREATED="1738185035229" ID="ID_485779056" MODIFIED="1738185093251" TEXT="noch eine Vereinfachung für Alternativen...">
|
||||
<arrowlink COLOR="#747687" DESTINATION="ID_944982552" ENDARROW="Default" ENDINCLINATION="306;23;" ID="Arrow_ID_1188443457" STARTARROW="None" STARTINCLINATION="467;31;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1737776743702" ID="ID_1501521982" MODIFIED="1737817618502" TEXT="sonderbares Verhalten mit zwe sub-Syntax-Klauseln und Binder">
|
||||
|
|
@ -57747,9 +57843,10 @@
|
|||
<arrowlink COLOR="#a670c5" DESTINATION="ID_476963617" ENDARROW="Default" ENDINCLINATION="63;87;" ID="Arrow_ID_1307955722" STARTARROW="None" STARTINCLINATION="391;0;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1737509793049" ID="ID_1654271031" MODIFIED="1738091231539" TEXT="erwartete Verwendung im Test durchspielen">
|
||||
<node COLOR="#338800" CREATED="1737509793049" ID="ID_1654271031" MODIFIED="1738184702812" TEXT="erwartete Verwendung im Test durchspielen">
|
||||
<arrowlink COLOR="#69a19e" DESTINATION="ID_1564220447" ENDARROW="Default" ENDINCLINATION="365;-30;" ID="Arrow_ID_30873436" STARTARROW="None" STARTINCLINATION="-288;17;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<arrowlink COLOR="#69a19e" DESTINATION="ID_984253455" ENDARROW="Default" ENDINCLINATION="207;0;" ID="Arrow_ID_1995388637" STARTARROW="None" STARTINCLINATION="-288;17;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#0d4d48" CREATED="1738089850124" ID="ID_169271928" MODIFIED="1738092642222" TEXT="Beispiel: numerischer Ausdruck">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1738089863497" ID="ID_988046108" MODIFIED="1738091511457" TEXT="»der Klassiker«">
|
||||
|
|
@ -57788,6 +57885,7 @@
|
|||
</node>
|
||||
<node CREATED="1738090134820" ID="ID_1211990966" MODIFIED="1738090144679" TEXT="dafür kann der Visitor einen Wert liefern"/>
|
||||
<node COLOR="#435e98" CREATED="1738090145459" ID="ID_944982552" MODIFIED="1738090158609" TEXT="vordefiniert als AltModel::getAny()">
|
||||
<linktarget COLOR="#747687" DESTINATION="ID_944982552" ENDARROW="Default" ENDINCLINATION="306;23;" ID="Arrow_ID_1188443457" SOURCE="ID_485779056" STARTARROW="None" STARTINCLINATION="467;31;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f4a" CREATED="1738090228760" ID="ID_1868530708" MODIFIED="1738090248792" TEXT="compiliert nur bei kompatiblen Typen"/>
|
||||
|
|
@ -57807,6 +57905,7 @@
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#8f8aac" DESTINATION="ID_1009402167" ENDARROW="Default" ENDINCLINATION="545;-25;" ID="Arrow_ID_1645190934" SOURCE="ID_1210934055" STARTARROW="None" STARTINCLINATION="798;36;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e4eda1" COLOR="#007199" CREATED="1738090286760" ID="ID_1538254940" MODIFIED="1738090327155" STYLE="fork" TEXT="kann Φ ausrechnen">
|
||||
|
|
@ -57817,9 +57916,9 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1738092650202" ID="ID_1683123511" MODIFIED="1738092666047" TEXT="Beispiel: verschachtelte Definition">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#c8b8b6" COLOR="#464398" CREATED="1738092667144" ID="ID_195611513" MODIFIED="1738093265339" TEXT="der Anlaß warum ich dieses Parser-Framework baue...">
|
||||
<node COLOR="#338800" CREATED="1738092650202" ID="ID_1683123511" MODIFIED="1738184455603" TEXT="Beispiel: verschachtelte Definition">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#c8b8b6" COLOR="#464398" CREATED="1738092667144" ID="ID_195611513" MODIFIED="1738185016897" TEXT="der Anlaß warum ich dieses Parser-Framework baue...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -57828,7 +57927,7 @@
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#2469a2" DESTINATION="ID_461276578" ENDARROW="Default" ENDINCLINATION="1338;-36;" ID="Arrow_ID_1078242662" STARTARROW="Default" STARTINCLINATION="1431;72;"/>
|
||||
<arrowlink COLOR="#2469a2" DESTINATION="ID_461276578" ENDARROW="Default" ENDINCLINATION="1338;-36;" ID="Arrow_ID_1078242662" STARTARROW="Default" STARTINCLINATION="1743;85;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1738122898074" ID="ID_1357593394" MODIFIED="1738122916309" TEXT="Ansatz">
|
||||
|
|
@ -57858,7 +57957,7 @@
|
|||
<node COLOR="#338800" CREATED="1738123171366" ID="ID_276974401" MODIFIED="1738123177620" TEXT="funktioniert grundsätzlich">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1738123178974" ID="ID_1533306886" MODIFIED="1738123194597" TEXT="interessantes Fehlverhalten im Test">
|
||||
<node COLOR="#435e98" CREATED="1738123178974" ID="ID_1533306886" MODIFIED="1738183220672" TEXT="subtiles Fehlverhalten im Test">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1738123415378" ID="ID_1843918790" MODIFIED="1738123415378" TEXT="apply(spec)(" prey .( haul \",loot!") ? = prey .(">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#b0020b" CREATED="1738123430342" HGAP="69" ID="ID_1506770904" MODIFIED="1738123808483" TEXT="hätte die öffnende Klammer nicht mitnehmen dürfen" VSHIFT="-1">
|
||||
|
|
@ -57872,11 +57971,73 @@
|
|||
<font NAME="SansSerif" SIZE="11"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1738182888797" ID="ID_1993951028" MODIFIED="1738182912516">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Beobachtung: beide haben zwei <b>führende Leerzeichen</b>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1738182914123" ID="ID_394609963" MODIFIED="1738182928052" TEXT="bestätigt: wenn man die wegläßt..."/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1738183187384" ID="ID_343204836" MODIFIED="1738183346750" TEXT="Fehler in bindMatch ⟶ toStringConnex">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1738183227236" ID="ID_1686109910" MODIFIED="1738183247164" TEXT="hier der fallback-Zweig wirksam">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1738183248251" ID="ID_740895759" MODIFIED="1738183344746" TEXT="wir ermitteln nochmal erneut den leading Whitespace">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
das liegt daran, daß wir diese Info nicht aufzeichnen, weil generell das Akzeptieren (und Backtracking) durch rekursiven Funktionsaufruf auf Substrings realisiert ist...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1738183296979" ID="ID_643934059" MODIFIED="1738183337373" TEXT="wenn vorne ein Präfix wegfällt, muß natürlich die Länge gekürzt werden!">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1737048820482" ID="ID_235554745" MODIFIED="1737048832524" TEXT="generisches Model-Binding"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1738186832857" ID="ID_175116703" MODIFIED="1738186839257" TEXT="Fazit">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1738186840421" ID="ID_795784976" MODIFIED="1738186853307" TEXT="ein Header lib/parse.hpp mit minimalen Dependencies"/>
|
||||
<node CREATED="1738186854355" ID="ID_1978636423" MODIFIED="1738186880579" TEXT="DSL-Einstieg util::parse::accept(SPEC)"/>
|
||||
<node CREATED="1738186885365" ID="ID_966881156" MODIFIED="1738186905222" TEXT="Recursive-Descent LL(n)-Parser ohne Lexer"/>
|
||||
<node CREATED="1738186909557" ID="ID_1064621860" MODIFIED="1738186931396" TEXT="Parser-Kombinator-Technik eingebettet in eine DSL">
|
||||
<node CREATED="1738186932909" ID="ID_1673393435" MODIFIED="1738186950076" TEXT="Kombinatoren sind reine Implementierungs-Technik"/>
|
||||
<node CREATED="1738186951862" ID="ID_1935160846" MODIFIED="1738186986013" TEXT="Syntax-Objekt als Kapsel mit DSL — keine überladenen Operatoren"/>
|
||||
<node CREATED="1738187102068" ID="ID_247180538" MODIFIED="1738187128828" TEXT="funktionaler Ansatz für Backtracking und Model-Binding"/>
|
||||
</node>
|
||||
<node CREATED="1738187009166" ID="ID_1048355173" MODIFIED="1738187047066" TEXT="Kein Syntax-Baum — stattdessen komplex verschachtelte explizite λ-Typen"/>
|
||||
<node CREATED="1738187071641" ID="ID_63380090" MODIFIED="1738187073702" TEXT="Aufbau">
|
||||
<node CREATED="1738187077563" ID="ID_147014086" MODIFIED="1738187098670" TEXT="Eval ⟵ Parse-Ergebnis"/>
|
||||
<node CREATED="1738188401579" ID="ID_77338495" MODIFIED="1738188426340" TEXT="Connex ⟵ Parser-Funktionsbaustein"/>
|
||||
<node CREATED="1738188435390" ID="ID_1061346176" MODIFIED="1738188450792" TEXT="buildXXConnex ⟵ die Kombinatoren als freie Funktionen"/>
|
||||
<node CREATED="1738188451684" ID="ID_1681615382" MODIFIED="1738188464223" TEXT="Parser ⟵ Interface über einen Connex"/>
|
||||
<node CREATED="1738188464959" ID="ID_652466565" MODIFIED="1738188493194" TEXT="Syntax ⟵ verbindet Parser und ein Eval-State + DSL"/>
|
||||
</node>
|
||||
<node CREATED="1738188522420" ID="ID_815505663" MODIFIED="1738188532853" TEXT="Anwendung">
|
||||
<node CREATED="1738188533801" ID="ID_754612180" MODIFIED="1738188565308" TEXT="eine Syntax aufbauen">
|
||||
<icon BUILTIN="full-1"/>
|
||||
</node>
|
||||
<node CREATED="1738188547420" ID="ID_1858683440" MODIFIED="1738188567655" TEXT="auf dieser die parse()-Funktion aufrufen">
|
||||
<icon BUILTIN="full-2"/>
|
||||
</node>
|
||||
<node CREATED="1738188555935" ID="ID_972096316" MODIFIED="1738188570346" TEXT="Ergebnis-State auswerten">
|
||||
<icon BUILTIN="full-3"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1736884111530" ID="ID_1649572298" MODIFIED="1736897372481" TEXT="Parse_test">
|
||||
|
|
@ -57943,8 +58104,31 @@
|
|||
<linktarget COLOR="#69a19e" DESTINATION="ID_1564220447" ENDARROW="Default" ENDINCLINATION="365;-30;" ID="Arrow_ID_30873436" SOURCE="ID_1654271031" STARTARROW="None" STARTINCLINATION="-288;17;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1737845308863" ID="ID_383219766" MODIFIED="1737845313627" TEXT="simpleUsage">
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1737845314577" ID="ID_453689160" MODIFIED="1737845324102" TEXT="puh ... was zeigen wir da?">
|
||||
<node COLOR="#338800" CREATED="1738184503016" ID="ID_1456096857" MODIFIED="1738184539829" TEXT="nested backets/quotes">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1738184543947" ID="ID_988653432" MODIFIED="1738184595763" TEXT="der tatsächliche Anwendungsfall...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...der diese Entwicklung eines Parser-Frameworks angestoßen hat
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1738184597252" ID="ID_220015780" MODIFIED="1738184697143" TEXT="schrittweise aufbauen">
|
||||
<node CREATED="1738184602060" ID="ID_1298384168" MODIFIED="1738184604647" TEXT="quotes"/>
|
||||
<node CREATED="1738184605163" ID="ID_379105406" MODIFIED="1738184609791" TEXT="escapes"/>
|
||||
<node CREATED="1738184610378" ID="ID_1369081517" MODIFIED="1738184614550" TEXT="geklammerter Term"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1737509774878" ID="ID_984253455" MODIFIED="1738184687735" TEXT="dann die volle Spezifikations-Syntax zusammengesetzt">
|
||||
<linktarget COLOR="#69a19e" DESTINATION="ID_984253455" ENDARROW="Default" ENDINCLINATION="207;0;" ID="Arrow_ID_1995388637" SOURCE="ID_1654271031" STARTARROW="None" STARTINCLINATION="-288;17;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1737845308863" ID="ID_383219766" MODIFIED="1738195025527" TEXT="simpleUsage">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1737845314577" ID="ID_453689160" MODIFIED="1738195028122" TEXT="puh ... was zeigen wir da?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1737845330906" ID="ID_775079358" MODIFIED="1737845372016" TEXT="nicht zu komplex machen">
|
||||
<icon BUILTIN="yes"/>
|
||||
|
|
@ -57953,6 +58137,9 @@
|
|||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1738188654289" ID="ID_333857981" MODIFIED="1738195032916" TEXT="Term mit Argument-Token">
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -105160,9 +105347,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1738092795598" ID="ID_461276578" MODIFIED="1738093238630" TEXT="uuuuund ... kaum wart' ma zwei Wochen, schon können wir das">
|
||||
<node CREATED="1738092795598" ID="ID_461276578" MODIFIED="1738185016897" TEXT="uuuuund ... kaum wart' ma zwei Wochen, schon können wir das">
|
||||
<arrowlink COLOR="#996494" DESTINATION="ID_1363201028" ENDARROW="Default" ENDINCLINATION="-20;-32;" ID="Arrow_ID_621419348" STARTARROW="None" STARTINCLINATION="195;9;"/>
|
||||
<linktarget COLOR="#2469a2" DESTINATION="ID_461276578" ENDARROW="Default" ENDINCLINATION="1338;-36;" ID="Arrow_ID_1078242662" SOURCE="ID_195611513" STARTARROW="Default" STARTINCLINATION="1431;72;"/>
|
||||
<linktarget COLOR="#2469a2" DESTINATION="ID_461276578" ENDARROW="Default" ENDINCLINATION="1338;-36;" ID="Arrow_ID_1078242662" SOURCE="ID_195611513" STARTARROW="Default" STARTINCLINATION="1743;85;"/>
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue