1[/ 2 (C) Copyright Edward Diener 2011-2015 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt). 6] 7 8[section:vmd_sequence Parsing sequences] 9 10In the normal use of Boost PP data is passed as arguments to a macro in 11discrete units so that each parameter expects a single data type. A typical 12macro might be: 13 14 #define AMACRO(anumber,atuple,anidentifier) someoutput 15 16where the 'atuple', having the form of ( data1, data2, data3 ), itself may 17contain different data types of elements. 18 19This is the standard macro design and internally it is the easiest way 20to pass macro data back and forth. The Boost PP library has a rich set of 21functionality to deal with all of its high-level data types, and variadic data, 22with its own simpler functionality, also offers another alternative to 23representing data. 24 25Occasionally designers of macros, especially for the use of others programmers within 26a particular library, have expressed the need for a macro parameter to allow a more 27C/C++ like syntax where a single parameter might mimic a C++ function-call or a 28C-like type modification syntax, or some other more complicated construct. 29Something along the lines of: 30 31 areturn afunction ( aparameter1, aparameter2, aparameter3 ) 32 33or 34 35 ( type ) data 36 37etc. etc. 38 39In other words, from a syntactical level when designing possible macro input, 40is it possible to design parameter data to look more like C/C++ when macros 41are used in a library and still do a certain amount of preprocessor metaprogramming 42with such mixed token input ? 43 44VMD has functionality which allows more than one type of preprocessing token, 45excluding an 'empty' token which always refers to some entire input, to be part of a 46single parameter of input data. These preprocessing tokens as a single parameter are 47syntactically a consecutive series of data. The single limitation of this consecutive 48series of data is that each top-level part of the data of this series is of some VMD data type. 49What this means is that if some input consists of a series of data types it is possible 50to extract the data for each data type in that series. 51 52In practicality what this means is that, given the examples just above, if 53'areturn', 'afunction', and 'data' are identifiers it would be possible to 54parse either of the two inputs above so that one could identify the different 55data types involved and do preprocessor metaprogramming based on those results. 56 57[heading Sequence definition] 58 59I will be calling such input data, which consists of all top-level data types in a series, 60by the term of a 'sequence'. Each separate data type in the sequence is called an 'element'. 61In this definition of a 'sequence' we can have 0 or more elements, so that a sequence 62is a general name for any VMD input. A sequence is therefore 63any input VMD can parse, whether it is emptiness, a single element, or more than one 64element in a series. Therefore when we speak of VMD macros parsing input data we are 65really speaking of VMD macros parsing a sequence. A sequence can therefore also be part of 66a Boost PP composite data type, or variadic data, and VMD can still parse such an embedded 67sequence if asked to do so. 68 69[heading Sequence parsing] 70 71Parsing a sequence means that VMD can step through each element of a sequence 72sequentially, determine the type and data of each element, then move on to the 73next element. Parsing is sequential and can only be done in a forward direction, 74but it can be done any number of times. In C++ iterator terms parsing of a 75sequence is a forward iterator. 76 77Working with a sequence is equivalent to using VMD macros 'generically'. 78 79Before I give an explanation of how to use a sequence using VMD generic 80functionality I would like to make two points: 81 82* The possibility of working with a sequence which contains more than one 83data type can be easily abused. In general 84keeping things simple is usually better than making things overly complicated 85when it comes to the syntactical side of things in a computer language. A macro 86parameter syntactical possibility has to be understandable to be used. 87* Using VMD to parse the individual data types of a sequence takes more 88preprocessing time than functionality offered with Boost PP data types, 89because it is based on forward access through each top-level type of the sequence. 90 91The one constraint in a sequence is that the top-level must 92consist of VMD data types, in other words preprocessor tokens which VMD understands. 93By top-level it is meant that a Boost PP composite data may have elements which 94VMD cannot parse but as long as the input consists of the composite data types and 95not the inner unparsable elements, VMD can parse the input. 96Therefore if preprocessor data is one of the examples above, you will be successful 97in using VMD. However if your preprocessor data takes the form of: 98 99 &name identifier ( param ) 100 101or 102 103 identifier "string literal" 104 105or 106 107 identifier + number 108 109or 110 111 identifier += 4.3 112 113etc. etc. 114 115you will not be able to parse the data using VMD since '&', "string literal", 116'+', '+=', and "4.3" are preprocessor tokens which are not VMD top-level data types and 117therefore VMD cannot handle them at the parsing level. You can still of course 118pass such data as preprocessing input to macros but you cannot use VMD to recognize 119the parts of such data. 120 121This is similar to the fact that VMD cannot tell you what type preprocessor data 122is as a whole, using any of the VMD identifying macros already discussed, if the 123type is not one that VMD can handle. 124 125On the other hand you can still use VMD to parse such tokens in the input if you use 126Boost PP data types as top-level data types to do so. Such as: 127 128 ( &name ) identifier ( param ) 129 130or 131 132 identifier ( "string literal" ) 133 134or 135 136 identifier ( + ) number 137 138or 139 140 identifier ( += ) 4 ( . ) 3 141 142The succeeding topics explain the VMD functionality for parsing a sequence 143for each individual VMD data type in that sequence. 144 145[heading Sequence types] 146 147A VMD sequence can be seen as one of either three general types: 148 149# An empty sequence 150# A single element sequence 151# A multi-element sequence 152 153An empty sequence is merely input that is empty, what VMD calls "emptiness". Use the previously 154explained BOOST_VMD_IS_EMPTY macro to test for an empty sequence. 155 156 #include <boost/vmd/is_empty.hpp> 157 158 #define AN_EMPTY_SEQUENCE 159 160 BOOST_VMD_IS_EMPTY(AN_EMPTY_SEQUENCE) will return 1 161 162The type of an empty sequence is BOOST_VMD_TYPE_EMPTY. 163 164A single element sequence is a single VMD data type. This is what 165we have been previously discussing as data which VMD can parse in this 166documentation with our identifying macros. You can use the 167BOOST_VMD_IS_UNARY macro to test for a single element sequence. 168 169 #include <boost/vmd/is_unary.hpp> 170 171 #define A_SINGLE_ELEMENT_SEQUENCE (1,2) 172 173 BOOST_VMD_IS_UNARY(A_SINGLE_ELEMENT_SEQUENCE) will return 1 174 175The type of a single element sequence is the type of the individual data type. 176In our example above the type of A_SINGLE_ELEMENT_SEQUENCE is BOOST_VMD_TYPE_TUPLE. 177 178A multi-element sequence consists of more than one data type. This is the 179"new" type which VMD can parse. You can use the BOOST_VMD_IS_MULTI macro 180to test for a multi-element sequence. 181 182 #define A_MULTI_ELEMENT_SEQUENCE (1,2) (1)(2) 45 183 184The A_MULTI_ELEMENT_SEQUENCE consists of a tuple followed by a seq followed by a number. 185 186 #include <boost/vmd/is_multi.hpp> 187 188 BOOST_VMD_IS_MULTI(A_MULTI_ELEMENT_SEQUENCE) will return 1 189 190The type of a multi-element sequence is always BOOST_VMD_TYPE_SEQUENCE. 191 192The type of a sequence can be obtained generically with the BOOST_VMD_GET_TYPE 193macro. We will be explaining this further in the documentation. 194 195[heading Sequence size] 196 197The size of any sequence can be accessed using the BOOST_VMD_SIZE macro. 198For an empty sequence the size is always 0. For a single element sequence 199the size is always 1. For a multi-element sequence the size is the number 200of individual top-level data types in the sequence. 201 202 #include <boost/vmd/size.hpp> 203 204 BOOST_VMD_SIZE(AN_EMPTY_SEQUENCE) will return 0 205 BOOST_VMD_SIZE(A_SINGLE_ELEMENT_SEQUENCE) will return 1 206 BOOST_VMD_SIZE(A_MULTI_ELEMENT_SEQUENCE) will return 3 207 208[heading Distinguishing consecutive seqs and tuples in a sequence] 209 210As has previously been mentioned a single element tuple 211is also a one element seq, so parsing a sequence which 212has seqs and tuples in them might be a problem as far 213as identify each element of the sequence. In a multi-element 214sequence if the data consists of a mixture of seqs 215and tuples consecutively we need to distinguish how VMD parses the data. 216The rule is that VMD always parses a single element tuple as a tuple unless it is 217followed by one or more single element tuples, in which case it is a seq. 218Here are some examples showing how the rule is applied. 219 220 #define ST_DATA (somedata)(element1,element2) 221 222VMD parses the above data as 2 consecutive tuples. 223The first tuple is the single element tuple '(somedata)' and the second tuple 224is the multi element tuple '(element1,element2)'. 225 226 #define ST_DATA (element1,element2)(somedata) 227 228VMD parses the above data as 2 consecutive tuples. 229The first tuple is the multi element tuple '(element1,element2)' and the second tuple 230is the single element tuple '(somedata)'. 231 232 #define ST_DATA (somedata)(some_other_data)(element1,element2) 233 234VMD parses the above data as a seq followed by a tuple. 235The seq is '(somedata)(some_other_data)' and the tuple is 236'(element1,element2)'. 237 238[heading Using VMD to parse sequence input] 239 240For a VMD sequence two ways of parsing into individual data 241types are offered by the VMD library: 242 243# The sequence can be converted to any of the Boost PP data types, or 244to variadic data, where each individual data type in the sequence becomes 245a separate element of the particular composite data type chosen. The 246conversion to a particular Boost PP data type or variadic data is slow, 247because it is based on forward access through each top-level type of the sequence, 248but afterwards accessing any individual element is as fast as accessing 249any element in the Boost PP data type or among variadic data. 250# The sequence can be accessed directly through its individual elements. 251This is slower than accessing an element of a Boost PP data type 252or variadic data but offers conceptual access to the original sequence 253as a series of elements. 254 255These two techniques will be discussed in succeeding topics. 256 257[include vmd_sequence_convert.qbk] 258[include vmd_sequence_access.qbk] 259 260[endsect] 261