Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Parsing v-identifiers using optional parameters

While parsing an v-sequence starting with a v-identifier can always be done for the fairly simple v-sequences situations previously mentioned, it is more challenging to do so when the v-identifier is followed by one or more other v-identifiers, or more than one v-number, or a combination of the two possible v-sequences. To do this one needs to use optional parameters to the BOOST_VMD_IDENTIFIER macro.

Recall that the BOOST_VMD_IDENTIFIER macro takes two mandatory parameters, the v-sequence and the v-key for the beginning identifier being parsed. The BOOST_VMD_IDENTIFIER macro also takes optional parameters to parse the more difficult sequences involving further v-identifiers or v-numbers.

Complicated v-sequences

Before I explain the optional parameters here are the forms of the more difficult v-sequences which BOOST_VMD_IDENTIFIER can parse with their help:

v-identifier v-identifier ... v-number-or-tuple-or-end-of-input
v-identifier v-number v-number ... tuple-or-end-of-input
v-identifier v-identifier ... v-number v-number ...tuple-or-end-of-input

These three supported situations allow * a v-identifier to be followed by from one to four additional v-identifiers followed by either a single v-number ( followed by a tuple or end-of-sequence ), tuple, or end-of-sequence. * a v-identifier to be followed by from two to five v-numbers before encountering either a tuple or end-of-sequence. * a v-identifier to be followed by from one to four additional v-identifiers, followed by from two to five v-numbers before encountering a tuple or end-of-sequence.

Parsing input sequences beginning with v-identifier(s), immediately followed by v-number(s), immediately followed by further v-identifier(s) are not supported. But of course this can be modified by having v-identifier(s), immediately followed followed by v-number(s), immediately followed followed by a tuple, followed by further v-identifier(s), which is supported in the third case above.

I am not necessarily advocating using such complicated sequences. It is more likely that a better design may have v-identifiers or v-numbers be separate elements of a tuple rather than consecutive elements of some v-sequence. While a reasonable case can be made for v-sequences of consecutive v-identifiers, since C++ mimics such syntax in a number of cases, certainly consecutive v-numbers would normally better be served in a tuple or seq or as variadic data rather than in a macro v-sequence, since the syntax of nnn nnn nnn nnn ... is not naturally seen in standard C++ as opposed to nnn,nnn,nnn,nnn ... .

Using the optional 3rd parameter

In order to find a v-identifier at the beginning of a v-sequence when it could be followed by a maximum of four subsequent v-identifiers, the optional 3rd parameter to BOOST_VMD_IDENTIFIER must be used. This is our v-sequence of:

v-identifier v-identifier ... v-number-or-tuple-or-end-of-input

This optional 3rd parameter is a seq, where each element is a v-key to possible subsequent v-identifiers. You can specify more seq elements than are actually found in the input v-sequence as long as the seq elements specified match v-identifiers that are found.

Some examples:

#define BOOST_VMD_MAP_MYLIB_KEY6_APPLE
#define BOOST_VMD_MAP_MYLIB_KEY7_BANANA
#define BOOST_VMD_MAP_MYLIB_KEY8_CHERRY
#define BOOST_VMD_MAP_MYLIB_KEY9_ORANGE
#define BOOST_VMD_MAP_MYLIB_KEY10_PEACH
#define BOOST_VMD_MAP_MYLIB_KEY11_PEAR

#define SOME_INPUT6 CHERRY BANANA PEACH (telem1,telem2)

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT6 /* v-sequence */,
  MYLIB_KEY8_ /* CHERRY, key which matches */,
  /* The optional 3rd parameter as a seq */
  ((MYLIB_KEY11_ /* PEAR */,MYLIB_KEY7_ /* BANANA, which matches */))
  (MYLIB_KEY10_ /* PEACH, which matches */)
  ((MYLIB_KEY6_ /* APPLE */,MYLIB_KEY9_ /* ORANGE */))
  /* This last seq element is extraneous for the particular input
     because the first two seq elements cover the two subsequent
     v-identifiers. But this shows you can have extra seq elements
     without affecting the ability to match */
  )

expands to (1,BANANA PEACH (telem1,telem2))

#define SOME_INPUT7 PEAR ORANGE APPLE PEACH 27

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT7 /* v-sequence */,
  (MYLIB_KEY6_ /* APPLE */,MYLIB_KEY11_ /* PEAR, key which matches */),
  /* The optional 3rd parameter as a seq */
  (MYLIB_KEY9_ /* ORANGE, which matches */)
  ((MYLIB_KEY7_ /* BANANA */,MYLIB_KEY6_ /* APPLE, which matches */))
  /* No subsequent seq element to match PEACH so beginning v-identifier
     is not found */
  )

expands to (0,)

The optional 3rd parameter is also used in order to find a v-identifier at the beginning of a v-sequence when it is followed by more than one v-number before a tuple or end-of-sequence is encountered. This is our v-sequence of:

v-identifier v-number v-number ... tuple-or-end-of-input

In this case the optional 3rd parameter is just a number, with a maximum of five, which specifies the maximum number of v-numbers which can follow the beginning identifier. You can specify a number which is greater than the actual number of v-numbers which follow the beginning v-identifier and the parsing will still succeed as long as the beginning v-identifier is found. But if you specify a number that is less than the number of subsequent v-numbers, the parsing will fail. You never need to specify the optional 3rd parameter as a number if the v-identifier in the beginning of a v-sequence is followed by a single v-number, but you are allowed to do so.

Some examples, using our key-identifier macros above:

#define SOME_INPUT8 APPLE 37 142 (telem1,telem2)

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT8 /* v-sequence */,
  ( MYLIB_KEY10_ /* PEACH */, MYLIB_KEY6_ /* APPLE, key which matches */ ),
  /* The optional 3rd parameter as a number */
  3 /* succeeds because there are less than or equal to 3 following v-numbers */
  )

expands to (2,37 142 (telem1,telem2))

#define SOME_INPUT9 ORANGE 25 99 234 56

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT9 /* v-sequence */,
  MYLIB_KEY9_ /* ORANGE, key which matches */,
  /* The optional 3rd parameter as a number */
  2 /* fails because there are more than 2 following v-numbers */
  )

expands to (0,)

#define SOME_INPUT10 BANANA 226

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT10 /* v-sequence */,
  MYLIB_KEY7_ /* BANANA, key which matches */,
  /* The optional 3rd parameter as a number */
  1 /* Not needed but it does no harm */
  )

expands to (1,226)

Using the optional 4th parameter

The optional 4th parameter is used in order to find a v-identifier at the beginning of the v-sequence when it is followed by v-identifiers and more than one v-number before a tuple or end-of-sequence. This is our v-sequence of:

v-identifier v-identifier ... v-number v-number ...tuple-or-end-of-input

In this situation the optional 3rd parameter is the seq we used for subsequent v-identifiers and the optional 4th parameter is the number we used for subsequent v-numbers. When we use both optional parameters we may still succeed if we encounter a single v-number ( followed by a tuple or end-of-sequence ), tuple, or end-of-sequence before the seq matches are exhausted or, once we start matching v-numbers, if we encounter a tuple or end-of-sequnce before the number matches are exhausted. But once we encounter consecutive v-numbers in the v-sequence, we need to have matched exactly the number of seqs specified.

Some examples, using our key-identifier macros above:

#define SOME_INPUT11 CHERRY BANANA 25 99 234 (telem1,telem2)

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT11 /* v-sequence */,
  MYLIB_KEY8_ /* CHERRY, key which matches */,
  ((MYLIB_KEY11_ /* PEAR */,MYLIB_KEY7_ /* BANANA, which matches */)),
  4 /* succeeds because there are less than or equal to 4 following v-numbers */
  )

expands to (1,BANANA 25 99 234 (telem1,telem2))

#define SOME_INPUT12 PEAR ORANGE 8

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT12 /* v-sequence */,
  (MYLIB_KEY11_ /* PEAR, key which matches */, MYLIB_KEY8_ /* CHERRY*/),
  ((MYLIB_KEY7_ /* BANANA */,MYLIB_KEY9_ /* ORANGE, which matches */))
  ((MYLIB_KEY9_ /* ORANGE */,MYLIB_KEY8_ /* CHERRY */)),
  /* This last seq element is extraneous for the particular input
     because the first seq element covers the subsequent
     v-identifier and there is at most one v-number. This shows you
     can have extra seq elements without affecting the ability to match
     as long as you have no following consecutive v-numbers. */
  2
  /* succeeds because there are less than or equal to 2 following v-numbers
     but is not needed for the particular input because only a single
     v-number occurs */
  )

expands to (1,ORANGE)

#define SOME_INPUT13 APPLE PEACH PEAR 37 42

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT13 /* v-sequence */,
  MYLIB_KEY6_ /* APPLE, key which matches */,
  ((MYLIB_KEY7_ /* BANANA */,MYLIB_KEY9_ /* ORANGE */,MYLIB_KEY10_ /* PEACH, which matches*/))
  (MYLIB_KEY11_ /* PEAR, which matches */)
  (MYLIB_KEY8_ /* CHERRY,
    this negates the match since consecutive v-numbers occur
    next in the v-sequence and the 4th parameter is specified.
    If the 4th parameter had not been specified then this seq
    element would have been extraneous but would not have negated
    the match. */),
  2
  )

expands to (0,)

#define SOME_INPUT14 BANANA CHERRY 142 50

BOOST_VMD_IDENTIFIER
  (
  SOME_INPUT14 /* v-sequence */,
  MYLIB_KEY7_ /* BANANA, key which matches */,
  ((MYLIB_KEY7_ /* BANANA */,MYLIB_KEY8_ /* CHERRY, which matches */,MYLIB_KEY10_ /* PEACH */)),
  3 /* succeeds because there are less than or equal to 3 following v-numbers */
  )

expands to (1,CHERRY 142 50)


PrevUpHomeNext