I don't have a whole lot of code to show for this one because I haven't managed to get anything to work, but the high level problem is that I am trying to create a series of parsers for a family of related languages. What I mean by this is that the languages will share many of the same constructs, but there won't be complete overlap. As a simple example, say I have an AST that is parameterized by some (completely contrived in this example) 'leaf' type:
template <typename t>
struct fooT {
std::string name;
t leaf;
};
One language may have t
instantiated as int
and one as double
. What I wanted to do was create a templated class or something that I could instantiate with different t
's and corresponding parser rules so that I could generate a series of composed parsers.
In my real example, I have a bunch of nested structures that are the same across the languages, but only have a couple of small variations at the very edges of the AST, so if I cannot compose the parsers in a good way, I will end up duplicating a bunch of parse rules, AST nodes, etc. I have actually gotten it to work by not putting it in a class and just very carefully arranging my header files and imports so that I can have 'dangling' parser rules with special names that can be assembled. A big downside of this is that I cannot include parsers for the multiple different languages within the same program -- precisely because of the name conflict that arises.
Does anybody have any ideas how I could approach this?
The nice thing about X3 is that you can generate parsers just as easily as you define them in the first place.
E.g.
Now let's define a generic parser maker:
This allows us to compose various grammars with various leaf types and skipper styles:
Let's Demo:
Live On Coliru
Prints
Advanced
For advanced scenarios (where you have separation of rule declaration and definitions across trnalsation units and/or you require dynamic switching), you can use the
x3::any_rule<>
holder.