]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
10 | In the normal use of Boost PP data is passed as arguments to a macro in | |
11 | discrete units so that each parameter expects a single data type. A typical | |
12 | macro might be: | |
13 | ||
14 | #define AMACRO(anumber,atuple,anidentifier) someoutput | |
15 | ||
16 | where the 'atuple', having the form of ( data1, data2, data3 ), itself may | |
17 | contain different data types of elements. | |
18 | ||
19 | This is the standard macro design and internally it is the easiest way | |
20 | to pass macro data back and forth. The Boost PP library has a rich set of | |
21 | functionality to deal with all of its high-level data types, and variadic data, | |
22 | with its own simpler functionality, also offers another alternative to | |
23 | representing data. | |
24 | ||
25 | Occasionally designers of macros, especially for the use of others programmers within | |
26 | a particular library, have expressed the need for a macro parameter to allow a more | |
27 | C/C++ like syntax where a single parameter might mimic a C++ function-call or a | |
28 | C-like type modification syntax, or some other more complicated construct. | |
29 | Something along the lines of: | |
30 | ||
31 | areturn afunction ( aparameter1, aparameter2, aparameter3 ) | |
32 | ||
33 | or | |
34 | ||
35 | ( type ) data | |
36 | ||
37 | etc. etc. | |
38 | ||
39 | In other words, from a syntactical level when designing possible macro input, | |
40 | is it possible to design parameter data to look more like C/C++ when macros | |
41 | are used in a library and still do a certain amount of preprocessor metaprogramming | |
42 | with such mixed token input ? | |
43 | ||
44 | VMD has functionality which allows more than one type of preprocessing token, | |
45 | excluding an 'empty' token which always refers to some entire input, to be part of a | |
46 | single parameter of input data. These preprocessing tokens as a single parameter are | |
47 | syntactically a consecutive series of data. The single limitation of this consecutive | |
48 | series of data is that each top-level part of the data of this series is of some VMD data type. | |
49 | What this means is that if some input consists of a series of data types it is possible | |
50 | to extract the data for each data type in that series. | |
51 | ||
52 | In practicality what this means is that, given the examples just above, if | |
53 | 'areturn', 'afunction', and 'data' are identifiers it would be possible to | |
54 | parse either of the two inputs above so that one could identify the different | |
55 | data types involved and do preprocessor metaprogramming based on those results. | |
56 | ||
57 | [heading Sequence definition] | |
58 | ||
59 | I will be calling such input data, which consists of all top-level data types in a series, | |
60 | by the term of a 'sequence'. Each separate data type in the sequence is called an 'element'. | |
61 | In this definition of a 'sequence' we can have 0 or more elements, so that a sequence | |
62 | is a general name for any VMD input. A sequence is therefore | |
63 | any input VMD can parse, whether it is emptiness, a single element, or more than one | |
64 | element in a series. Therefore when we speak of VMD macros parsing input data we are | |
65 | really speaking of VMD macros parsing a sequence. A sequence can therefore also be part of | |
66 | a Boost PP composite data type, or variadic data, and VMD can still parse such an embedded | |
67 | sequence if asked to do so. | |
68 | ||
69 | [heading Sequence parsing] | |
70 | ||
71 | Parsing a sequence means that VMD can step through each element of a sequence | |
72 | sequentially, determine the type and data of each element, then move on to the | |
73 | next element. Parsing is sequential and can only be done in a forward direction, | |
74 | but it can be done any number of times. In C++ iterator terms parsing of a | |
75 | sequence is a forward iterator. | |
76 | ||
77 | Working with a sequence is equivalent to using VMD macros 'generically'. | |
78 | ||
79 | Before I give an explanation of how to use a sequence using VMD generic | |
80 | functionality I would like to make two points: | |
81 | ||
82 | * The possibility of working with a sequence which contains more than one | |
83 | data type can be easily abused. In general | |
84 | keeping things simple is usually better than making things overly complicated | |
85 | when it comes to the syntactical side of things in a computer language. A macro | |
86 | parameter syntactical possibility has to be understandable to be used. | |
87 | * Using VMD to parse the individual data types of a sequence takes more | |
88 | preprocessing time than functionality offered with Boost PP data types, | |
89 | because it is based on forward access through each top-level type of the sequence. | |
90 | ||
91 | The one constraint in a sequence is that the top-level must | |
92 | consist of VMD data types, in other words preprocessor tokens which VMD understands. | |
93 | By top-level it is meant that a Boost PP composite data may have elements which | |
94 | VMD cannot parse but as long as the input consists of the composite data types and | |
95 | not the inner unparsable elements, VMD can parse the input. | |
96 | Therefore if preprocessor data is one of the examples above, you will be successful | |
97 | in using VMD. However if your preprocessor data takes the form of: | |
98 | ||
99 | &name identifier ( param ) | |
100 | ||
101 | or | |
102 | ||
103 | identifier "string literal" | |
104 | ||
105 | or | |
106 | ||
107 | identifier + number | |
108 | ||
109 | or | |
110 | ||
111 | identifier += 4.3 | |
112 | ||
113 | etc. etc. | |
114 | ||
115 | you 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 | |
117 | therefore VMD cannot handle them at the parsing level. You can still of course | |
118 | pass such data as preprocessing input to macros but you cannot use VMD to recognize | |
119 | the parts of such data. | |
120 | ||
121 | This is similar to the fact that VMD cannot tell you what type preprocessor data | |
122 | is as a whole, using any of the VMD identifying macros already discussed, if the | |
123 | type is not one that VMD can handle. | |
124 | ||
125 | On the other hand you can still use VMD to parse such tokens in the input if you use | |
126 | Boost PP data types as top-level data types to do so. Such as: | |
127 | ||
128 | ( &name ) identifier ( param ) | |
129 | ||
130 | or | |
131 | ||
132 | identifier ( "string literal" ) | |
133 | ||
134 | or | |
135 | ||
136 | identifier ( + ) number | |
137 | ||
138 | or | |
139 | ||
140 | identifier ( += ) 4 ( . ) 3 | |
141 | ||
142 | The succeeding topics explain the VMD functionality for parsing a sequence | |
143 | for each individual VMD data type in that sequence. | |
144 | ||
145 | [heading Sequence types] | |
146 | ||
147 | A 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 | ||
153 | An empty sequence is merely input that is empty, what VMD calls "emptiness". Use the previously | |
154 | explained 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 | ||
162 | The type of an empty sequence is BOOST_VMD_TYPE_EMPTY. | |
163 | ||
164 | A single element sequence is a single VMD data type. This is what | |
165 | we have been previously discussing as data which VMD can parse in this | |
166 | documentation with our identifying macros. You can use the | |
167 | BOOST_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 | ||
175 | The type of a single element sequence is the type of the individual data type. | |
176 | In our example above the type of A_SINGLE_ELEMENT_SEQUENCE is BOOST_VMD_TYPE_TUPLE. | |
177 | ||
178 | A 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 | |
180 | to test for a multi-element sequence. | |
181 | ||
182 | #define A_MULTI_ELEMENT_SEQUENCE (1,2) (1)(2) 45 | |
183 | ||
184 | The 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 | ||
190 | The type of a multi-element sequence is always BOOST_VMD_TYPE_SEQUENCE. | |
191 | ||
192 | The type of a sequence can be obtained generically with the BOOST_VMD_GET_TYPE | |
193 | macro. We will be explaining this further in the documentation. | |
194 | ||
195 | [heading Sequence size] | |
196 | ||
197 | The size of any sequence can be accessed using the BOOST_VMD_SIZE macro. | |
198 | For an empty sequence the size is always 0. For a single element sequence | |
199 | the size is always 1. For a multi-element sequence the size is the number | |
200 | of 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 Using VMD to parse sequence input] | |
209 | ||
210 | For a VMD sequence essentially two ways of parsing into individual data | |
211 | types are offered by the VMD library: | |
212 | ||
213 | # The sequence can be converted to any of the Boost PP data types, or | |
214 | to variadic data, where each individual data type in the sequence becomes | |
215 | a separate element of the particular composite data type chosen. The | |
216 | conversion to a particular Boost PP data type or variadic data is slow, | |
217 | because it is based on forward access through each top-level type of the sequence, | |
218 | but afterwards accessing any individual element is as fast as accessing | |
219 | any element in the Boost PP data type or among variadic data. | |
220 | # The sequence can be accessed directly through its individual elements. | |
221 | This is slower than accessing an element of a Boost PP data type | |
222 | or variadic data but offers conceptual access to the original sequence | |
223 | as a series of elements. | |
224 | ||
225 | These two techniques will be discussed in succeeding topics. | |
226 | ||
227 | [include vmd_sequence_convert.qbk] | |
228 | [include vmd_sequence_access.qbk] | |
229 | ||
230 | [endsect] |