Commit graph

13 commits

Author SHA1 Message Date
41ded40a3a Library: add support for bracketed expressions
This is the very key feature that requires a real parser and can not be handled by regular expressions.

After all the groundwork, it is surprisingly easy provide now;
only coding up all those DSL-variants is tedious. Notably we also
support accepting an ''optional'' bracket, and we support arbitrary
expressions for the ''opening'' and ''closing construct.''
2025-01-24 01:41:55 +01:00
089fafc1bd Library: change DSL scheme to handle optional and repeated better
It seemed that using postfix-decorating operators would be a good fit
for the DSL. Exploring this idea further showed however, that such a scheme
is indeed a good fit from the implementation side, but leads to rather confusing
and hard to grasp DSL statements for many non-trivial syntax definition.
The reason is: such a postfix-decorator will by default work on ''everything defined''
up to that point; this is too much in many cases.

The other alternative would be a function-style definition, which has the benefit
to take the sub-clause directly as argument (so the scope is always explicit).
The downside is that argument arrangement is a bit more tricky for the repetition
combinator (there can be mis-matches, since we take the »SPEC« as free-template argument)
And, moreover, with function-style, having more top-level entrance points would
be helpful. Overall, no fundamental roadblock, just more technicalities in the setup
of the DSL functions.

With that re-arrangd structure, an optional combinator could be easily integrated,
and a solution was provided to pick up the parser function from a sub-expression
defined as Syntax object.
2025-01-23 19:48:30 +01:00
5fed95b929 Library: integrate repeated clauses into the DSL
Meanwhile, some kind of style scheme has emerged for the DSL:
We're working much with postfix-decorating operators, which
augment or extend the ''whole syntax clauses defined thus far''

In accordance with this scheme, I decided also to treat repeated expression
as a postfix operator (other than initially planned). This means, the actual
body to be repeated is ''the syntax clause defined thus far'', and the
repeat()-operator only details the number of repetitions and an optional delimiter.
2025-01-22 22:31:25 +01:00
6dc2561262 Library: draft mechanics for repetitive sequence 2025-01-22 16:42:28 +01:00
1a3781bbc0 Library: implementation of syntax-branching
...is now easy and follows entirely the scheme established thus far
2025-01-22 02:21:39 +01:00
e3fe8fe380 Library: use as a foundation for the branch-combinator
After all the preparation, now this panes out quite well:
 * use a simple 3-way branch structure
 * the model type was already pre-selected by the `_Join` Model selector
 * can just pass the result-model elements to a constructor/builder
 * incremental extension can be directly mapped to the predecessor model
2025-01-22 01:11:05 +01:00
4f676f7213 Library: test and documentation for the new variant-helper
So this turned out to be much more challenging than expected,
due to the fact that, with this design, typing information is
only available at compile-time. The key trick was to use a
''double-dispatch'' based on a generic lambda. In the end,
this could be rounded out to be self-contained library helper,
which is even fully copyable and assignable and properly
invokes all payload constructors and destructors.

The flip side is that such a design is obviously very flexible
and direct regarding the parser model-bindings, and it should
be fairly well optimisable, since the structure is entirely
static and without any virtual dispatch.

Proper handling of payload lifecycle was verified using
a tracking test object with checksum.
2025-01-21 04:53:53 +01:00
d052edf91d Library: try out building a variant-model on top
* the implementation of this ''Sum Type'' got quite technical and complicated;
   thus better to be extracted as separate library component
 * use this as base for the `AltModel`
 * make a usage sketch, invoking only the model interactions required
2025-01-21 01:02:07 +01:00
8c046ee2ea Library: generalise into a fully copyable type
After exploring the »nested decorator-chain« implementation variant,
I decided to stick to the solution with the λ-vistor, while attempting
to level and smooth-out the design.
 * allow to engage ''any'' «slot» at construction
 * reverse the order of type parameters to be ascending (as in `std::tuple`)
 * make it fully copyable, movable, assignable and provide a `swap()`,
   relying on a variant of the "copy-and-swap"-idiom
 * add an ''cross-constructor'' for an extended branch set
2025-01-20 20:22:16 +01:00
3e743ff3b5 Library: explore design of a Sum-Type
To represent the result-model for syntax alternatives,
we need a C++ representation for a ''sum type,'' i.e.
a type that can be one from a fixed set of alternatives.
Obviously the implementation will rely on some kind of Union,
or otherwise employ an opaque buffer and perform a forced cast.
Moreover, to be actually usable, a branch-selector-ID must be
captured and stored alongside, so that code processing the results
can detect which branch of the syntax was chosen.

There seem to be several possible avenues to build and structure
an actual class template to provide this implementation model
 * a nested decorator-chain
 * using a recursive selector-function with a generic-λ

''all these look quite unattractive, unfortunately....''
2025-01-19 23:14:03 +01:00
cf91f167dd Library: suppress leading whitespace automatically
Seems like a pragmatic choice, which simplifies most syntax definitions significantly.
In exceptional cases, it is still possible to enforce a situation with `\b` or `\B`
2025-01-18 22:25:03 +01:00
fb78c10996 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)
2025-01-18 04:22:37 +01:00
7998c8d724 Library: need support for specification parsing
Unfortunately, there are some common syntactic structures, which can not easily be dissected by regular expressions alone, since they entail nested subexpressions. While it is possible to get beyond those fundamental limitations with some trickery, doing so remains precisely that, ''trickery.''

After fighting some inner conflicts, since ''I do know how to write a parser'' —
in the end I have brought myself to just do it.

And indeed, as you'd might expect, I have looked into existing library solutions,
and I would not like to have any one of them as part of the project.
 * I do not want a ''parser engine'' or ''parser generator''
 * I want the directness of recursive-descent, but combined with Regular Expressions as terminal
 * I want to see the structure of the used grammar at the definition site of the custom parser function
 * I want deep integration of ''model bindings'' into the parse process, i.e. binding-λ
 * I do not want to write model-dissecting or pattern-matching code after the parse
 * I do not want to expose ''Monads'' as an interface, since they tend to spread unhealthy structure to surrounding code
 * I do not want to leak technicalities of the parse mechanics into the using code
 * I do not want to impose hard to remember specific conventions onto the user

Thus I've set the following aims:
 * The usage should require only a single header include (ideally header-only)
 * The entrance point should be a small number of DSL-starter functions
 * The parser shall be implemented by recursive-descent, using the parser-combinator technique
 * But I want that wrapped into a DSL, to be able to control what is (not) provided or exposed.
 * I want a stateful, applicative logic, since parsing, by its very nature, is stateful!
 * I want complete compile-time typing, visible to the optimiser, without a virtual »Parser« interface

And last but not least, ''I do not want to create a ticket, since I do not know if those goals can be achieved...''
2025-01-17 18:40:44 +01:00