Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 1 | NDN Regular Expression |
| 2 | ====================== |
| 3 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 4 | NDN regular expression is a kind of regular expression that can match NDN names. Matching is |
| 5 | performed at two levels: the name level and the name component level. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 6 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 7 | A name component matcher, enclosed in ``<`` and ``>``, specifies the pattern of a name component. The |
| 8 | component pattern is expressed with the `Perl Regular Expression Syntax |
Davide Pesavento | 844b093 | 2018-05-07 01:00:16 -0400 | [diff] [blame] | 9 | <https://www.boost.org/doc/libs/1_58_0/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html>`__. |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 10 | For example, ``<ab*c>`` matches the 1st, 3rd, and 4th components of ``/ac/dc/abc/abbc``, but does |
| 11 | not match the 2nd component. A special case is that ``<>`` denotes a wildcard matcher that can match |
| 12 | **ANY** name component. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 13 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 14 | A component matcher can match only one name component. To match a name, you need to compose an NDN |
| 15 | regular expression with zero or more name component matchers. For example, ``<ndn><edu><ucla>`` |
| 16 | matches the name ``/ndn/edu/ucla``. To describe a more complicated name pattern, we borrow some |
| 17 | syntaxes from the standard regular expressions. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 18 | |
| 19 | NDN Regex Syntax |
| 20 | ---------------- |
| 21 | |
| 22 | Anchors |
| 23 | ~~~~~~~ |
| 24 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 25 | The ``^`` character matches the start of a name. For example, ``^<ndn>`` matches any name starting |
| 26 | with the component ``ndn``, but does not match a name like ``/local/broadcast``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 27 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 28 | The ``$`` character matches the end of a name. For example, ``^<ndn><edu>$`` matches only one |
| 29 | name: ``/ndn/edu``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 30 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 31 | Repetition |
| 32 | ~~~~~~~~~~ |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 33 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 34 | A component matcher can be followed by a repeat quantifier to indicate how many times the preceding |
| 35 | component may appear. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 36 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 37 | The ``*`` quantifier denotes "zero or more times". For example, ``^<A><B>*<C>$`` matches ``/A/C``, |
| 38 | ``/A/B/C``, ``/A/B/B/C``, and so on. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 39 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 40 | The ``+`` quantifier denotes "one or more times". For example, ``^<A><B>+<C>$`` matches ``/A/B/C``, |
| 41 | ``/A/B/B/C``, and so on, but does not match ``/A/C``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 42 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 43 | The ``?`` quantifier denotes "zero or one time". For example, ``^<A><B>?<C>`` matches ``/A/C`` and |
| 44 | ``/A/B/C``, but does not match ``/A/B/B/C``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 45 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 46 | A bounded quantifier specifies a minimum and maximum number of permitted matches: ``{n}`` denotes |
| 47 | "exactly ``n`` times"; ``{n,}`` denotes "at least ``n`` times"; ``{,n}`` denotes "at most ``n`` |
| 48 | times"; ``{n, m}`` denotes "between ``n`` and ``m`` times (inclusive)". For example, |
| 49 | ``^<A><B>{2, 4}<C>$`` matches ``/A/B/B/C`` and ``/A/B/B/B/B/C``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 50 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 51 | Note that the quantifiers are **greedy**, which means it will consume as many matched components as |
| 52 | possible. NDN regular expressions currently do not support non-greedy repeat matching and possessive |
| 53 | repeat matching. For example, for the name ``/A/B/C/C/C``, ``^<A><B><C>+$`` will match the entire |
| 54 | name instead of only ``/A/B/C``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 55 | |
| 56 | Sets |
| 57 | ~~~~ |
| 58 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 59 | A name component set, denoted by a bracket expression starting with ``[`` and ending with ``]``, |
| 60 | defines a set of name components. It matches any single name component that is a member of that set. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 61 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 62 | Unlike standard regular expressions, NDN regular expression only supports **Single Components Set**, |
| 63 | that is, you have to list all the set members one by one between the brackets. For example, |
| 64 | ``^[<ndn><localhost>]`` matches any names starting with either ``ndn"`` or ``localhost`` component. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 65 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 66 | When a name component set starts with a ``'^'``, the set becomes a **Negation Set**. It matches the |
| 67 | complement of the contained name components. For example, ``^[^<ndn>]`` matches any non-empty name |
| 68 | that does not start with ``ndn`` component. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 69 | |
| 70 | Some other types of sets, such as Range Set, will be supported later. |
| 71 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 72 | Note that component sets may be repeated in the same way as component matchers. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 73 | |
| 74 | Sub-pattern and Back Reference |
| 75 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 76 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 77 | A section beginning ``(`` and ending ``)`` acts as a marked sub-pattern. Whatever matched the |
| 78 | sub-pattern is split out in a separate field by the matching algorithm. For example |
| 79 | ``^<A>(<>{2})<B>(<>)`` matches the name ``/A/C/D/B/E``, and the first sub-pattern captures ``C/D``. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 80 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 81 | Marked sub-patterns can be referred to by a back-reference ``\N``, which references one or more |
| 82 | capturing groups. In the example above, a back reference ``\1\2`` extracts ``/C/D/E`` out of the |
| 83 | name. |
Alexander Afanasyev | 7c6aeb0 | 2014-04-10 19:59:19 -0700 | [diff] [blame] | 84 | |
Alexander Afanasyev | c381bca | 2017-10-15 14:51:49 -0400 | [diff] [blame] | 85 | Marked sub-patterns can also be repeated. The regex engine does not permanently substitute |
| 86 | back-references in a regular expression, but will use the last match saved into the back-reference. |
| 87 | If a new match is found by capturing parentheses, the previous match is overwritten. For example, |
| 88 | both ``^([<A><B><C>]+)$`` and ``^([<A><B><C>])+$`` match ``/C/A/B``. However, the former regex |
| 89 | stores ``C/A/B`` as the first back-reference, while the latter one stores ``B``. That is because the |
| 90 | ``+`` quantifier in the latter NDN regular expression causes the marked sub-pattern to be matched |
| 91 | three times, and ``B`` is the last saved match. |