···
| `(?= )` | `(?= ${/1/})` | A **positive lookahead** checks whether interpolations match, and if so continues the matcher without changing the input. If it matches, it's essentially ignored. |
| `(?! )` | `(?! ${/1/})` | A **negative lookahead** checks whether interpolations _don't_ match, and if so continues the matcher without changing the input. If the interpolations do match the matcher is aborted. |
251
+
A couple of operators also support "short hands" that allow you to write
252
+
lookaheads or non-capturing groups a little quicker.
254
+
| Shorthand | Example | Description |
255
+
| --------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
256
+
| `:` | `:${/1/}` | A **non-capturing group** is like a regular group, but the interpolations matched inside it don't appear in the parser's output. |
257
+
| `=` | `=${/1/}` | A **positive lookahead** checks whether interpolations match, and if so continues the matcher without changing the input. If it matches, it's essentially ignored. |
258
+
| `!` | `!${/1/}` | A **negative lookahead** checks whether interpolations _don't_ match, and if so continues the matcher without changing the input. If the interpolations do match the matcher is aborted. |
We can combine and compose these operators to create more complex matchers.
For instance, we can extend the original example to only allow a specific set
of names by using the `|` operator:
···
We've now entirely changed the output of the parser for this matcher. Given that each
matcher can change its output, we're free to change the parser's output entirely.
348
-
By **returning a falsy value** in this matcher, we can also change the matcher to not have
349
-
matched, which would cause other matchers to treat it like a mismatch!
357
+
By returning `null` or `undefined` in this matcher, we can also change the matcher
358
+
to not have matched, which would cause other matchers to treat it like a mismatch!
import { match, parse } from 'reghex';
···
tag(['test'], 'node_name');
// ["test", .tag = "node_name"]
387
+
### Tagged Template Parsing
389
+
Any grammar in RegHex can also be used to parse a tagged template literal.
390
+
A tagged template literal consists of a list of literals alternating with
391
+
a list of "interpolations".
393
+
In RegHex we can add an `interpolation` matcher to our grammars to allow it
394
+
to parse interpolations in a template literal.
397
+
import { interpolation } from 'reghex';
399
+
const anyNumber = interpolation((x) => typeof x === 'number');
401
+
const num = match('num')`
402
+
${/[+-]?/} ${anyNumber}
405
+
parse(num)`+${42}`;
406
+
// ["+", 42, .tag = "num"]
409
+
This grammar now allows us to match arbitrary values if they're input into the
410
+
parser. We can now call our grammar using a tagged template literal themselves
414
+
import { interpolation } from 'reghex';
416
+
const anyNumber = interpolation((x) => typeof x === 'number');
418
+
const num = match('num')`
419
+
${/[+-]?/} ${anyNumber}
**That's it! May the RegExp be ever in your favor.**