or

Basic operator: it matches if one of its subrules (stored in the rules template parameter tuple) match the input. The subrules are tested in order, from rules[0] to rules[$-1].

The matching subrule parse trees is stored as its only child and its matches field will contain all the subrule matches, in order.

1 alias or!(literal!"abc", charRange!('a','z')) rule; // abc or, failing that, any letter between a and z.
2 ParseTree input = ParseTree("",false,[],"defg"); // low-level plumbing, the rules described here act on ParseTree's not strings.
3                                                  // It's equivalent to "defg" as input
4 auto result = rule(input);
5 
6 assert(result.successful); // OK
7 assert(result.matches == ["d"]); // stores the (in this case) only match
8 assert(result.children.length == 1); // one child, the result of "abc" or [a-z], depending on which rule succeeded.
9 
10 input.input = "abc"; // changing the input string;
11 assert(rule(input)).successful); // Still OK
12 input.input = "1abc";
13 assert(!rule(input)).successful); // NOK, does not begin by abc nor by [a-z]

If it fails, the last children will contain the failed node that matched furthest (longes match). That way, when printing, as sort of diagnostic is given:

1 alias or!(literal!"abc", and!(literal!"ab", charRange!('0','9'))) rule; // 'abc' or 'ab[0-9]'
2 ParseTree input = ParseTree("",false,[],"abd"); // equivalent to "abd"
3 
4 auto failure = rule(input);
5 writeln(failure);
6 /+
7 or (failure)
8  +-and (failure)
9     +-literal(ab) [0, 2]["ab"]
10     +-charRange(0,9) failure at line 0, col 2, after "ab" expected a char between '0' and '9', but got "d"
11 +/

So we know 'or' failed, that the 'and' sub-rule had the longest match, matching 'ab' and failing for [0-9] on index 2.

template or(rules...)
or
if (
rules.length > 0
)

Meta