Recursivity
Many grammars need to include themselves. There are many examples of this: Handling simple mathematical expressions, JSON, XML, etc...
In order to handle this, Abulafia provides the Recur<>
1 pattern. It's by far the most complex stock pattern the library has to offer, but it's extremely versatile.
How Recur Works
Recur<>
works by delaying the definition of the pattern through forward-declaration shenanigans. Using it requires a few steps:
- Forward declare a struct type, say
MyRecur
. - Declare an instance of
Recur<MyRecur>
- Define a pattern, using that instance as if it was fully defined already.
- Define MyRecur as struct depending on the type of the resulting pattern.
- Assign the pattern to the Recur
instance.
How to use Recur
This 5 step process is extremely convoluted. Thankfully, abulafia provides the ABU_Recur_Define()
macro that gets rid of most of that boilerplate.
Here's what it looks like in action:
auto create_pattern() { // steps #1 and #2 abu::Recur<struct MyRecur> my_recur; // step #3 auto pat = int_ | ( '(' >> my_recur % ',' >> ')'); // steps #4 and #5 ABU_Recur_Define(MyRecur, my_recur, pat); return my_recur; // Could also be: return pat; }
Declaring a rule pattern.
-
spirit::qi handles this through the
Rule<>
parser. Which is a bit of a kitchen sink entry point that was a necessary evil due to the lack of type inference.abu::Recur<>
does only one thing: handle recursion. ↩