1[/============================================================================== 2 Copyright (C) 2001-2010 Joel de Guzman 3 Copyright (C) 2001-2005 Dan Marsden 4 Copyright (C) 2001-2010 Thomas Heller 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8===============================================================================/] 9 10[section:expression Phoenix Expressions] 11 12A Phoenix Expression is a model of the __proto_expr__ Concept. These expressions 13are wrapped inside an [link phoenix.inside.actor Actor] template. The `actor` provides 14the function call operator which evaluates the expressions. 15The `actor` is the domain specific wrapper around Phoenix expressions. 16 17By design, Phoenix Expressions do not carry any information on how they will be 18evaluated later on. They are the data structure on which the `Actions` will work. 19 20The library provides a convenience template to define expressions: 21 22 template <template <typename> Actor, typename Tag, typename A0, ..., typename A1> 23 struct expr_ext 24 : proto::transform<expr_ext<Actor, Tag, A0, ..., A1> > 25 { 26 typedef __unspecified__ base_expr; 27 typedef Actor<base_expr> type; 28 29 typedef __unspecified__ proto_grammar; 30 31 static type make(A0 a0, ..., A1 a1); 32 }; 33 34 template <typename Tag, typename A0, ..., typename A1> 35 struct expr : expr_ext<actor, Tag, A0, ..., A1> {}; 36 37[*Notation] 38[variablelist 39 [[`A0...AN`] [Child node types]] 40 [[`a0...aN`] [Child node objects]] 41 [[`G0...GN`] [__proto__ grammar types]] 42] 43 44[*Expression Semantics] 45[table 46 [[Expression] [Semantics]] 47 [[`expr<Tag, A0...AN>::type`] [The type of Expression having tag `Tag` and `A0...AN` children]] 48 [[`expr<Tag, G0...GN>`] [A __proto__ grammar and __proto_pass_through_transform__]] 49 [[`expr<Tag, A0...AN>::make(a0...aN)`] [Returns a Phoenix Expression]] 50] 51 52[note 53 You might have noticed the template template argument `Actor` used in 54 `expr_ext`. This can be a user supplied custom Actor adding other member 55 functions or objects than the default `actor` template. See 56 [link phoenix.examples.extending_actors Extending Actors] for more details. 57] 58 59[heading meta_grammar] 60 61Defining expressions is only part of the game to make it a valid Phoenix Expression. 62In order to use the expressions in the Phoenix domain, we need to "register" them 63to our grammar. 64 65The `meta_grammar` is a struct for exactly that purpose. It is an openly extendable __proto__ Grammar: 66 67 struct meta_grammar 68 : proto::switch_<meta_grammar> 69 { 70 template <typename Tag, typename Dummy> 71 struct case_ 72 : proto::not_<proto::_> 73 {}; 74 }; 75 76As you can see, by default the `meta_grammar` matches nothing. With every [link phoenix.modules Module] 77you include this grammar gets extended by various expressions. 78 79[heading Example] 80 81Define an expression: 82 83 template <typename Lhs, typename Rhs> 84 struct plus 85 : expr<proto::tag::plus, Lhs, Rhs> 86 {}; 87 88And add it to the grammar: 89 90 template <> 91 struct meta_grammar::case_<proto::tag::plus> 92 : enable_rule< 93 plus< 94 meta_grammar 95 , meta_grammar 96 > 97 > 98 {}; 99 100Define a generator function to make the life of our potential users easier: 101 102 template <typename Lhs, typename Rhs> 103 typename plus<Lhs, Rhs>::type 104 plus(Lhs const & lhs, Rhs const & rhs) 105 { 106 return expression::plus<Lhs, Rhs>::make(lhs, rhs); 107 } 108 109Look if it really works: 110 111 plus(6, 5)(); 112 113returns 11! 114 115 proto::display_expr(plus(5, 6)); 116 117prints: 118 119 plus( 120 terminal(6) 121 , terminal(5) 122 ) 123 124See [@../../example/define_expression.cpp define_expression.cpp] for the full example. 125 126[note 127 The example shown here only works because `default_actions` knows how to handle 128 an expression having the `proto::tag::plus` and two children. This is because 129 `default_actions` uses the `proto::_default<meta_grammar>` transform to 130 evaluate operators and functions. Learn more about actions 131 [link phoenix.inside.actions here]. 132] 133 134[section Boilerplate Macros] 135 136When having more and more expressions, you start to realize that this is a very 137repetetive task. Phoenix provides boilerplate macros that make defining Phoenix 138Expressions as you have seen in the 139[link phoenix.inside.expression previous section] look like a piece of cake. 140 141 142[/ 143These expressions generate the following: 144* A tag (in the underlying namespace tag) 145* An expression 146* an expression type in namespace expression 147] 148 149[section BOOST_PHOENIX_DEFINE_EXPRESSION] 150 151[heading Description] 152 153`BOOST_PHOENIX_DEFINE_EXPRESSION` is a macro that can be used to generate all the 154necessary boilerplate to create Phoenix Expressions 155 156[heading Synopsis] 157 158 BOOST_PHOENIX_DEFINE_EXPRESSION( 159 (namespace_seq)(name) 160 , (child_grammar0) 161 (child_grammar1) 162 ... 163 ) 164 165[heading Semantics] 166 167The above macro generates the necessary code for an expression `name` in 168namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many 169children the expression will have and what `proto::grammar` they match. 170 171The macro should be used at global scope. `namespace_seq` shall be the sequence 172of namespaces under which the following symbols will be defined: 173 174 namespace tag 175 { 176 struct name; 177 } 178 179 namespace expression 180 { 181 template <typename A0, typename A1 ... typename AN> 182 struct name 183 : boost::phoenix::expr< 184 tag::name 185 , A0 186 , A1 187 ... 188 , AN 189 > 190 } 191 192 namespace rule 193 { 194 struct name 195 : boost::phoenix::expr< 196 child_grammar0 197 , child_grammar1 198 ... 199 , child_grammarN 200 > 201 {}; 202 } 203 204 namespace functional 205 { 206 struct make_name; // A polymorphic function object that can be called to create the expression node 207 } 208 209 namespace result_of 210 { 211 template <typename A0, typename A1 ... typename AN> 212 struct make_name; // The result type of the expression node 213 } 214 215 // convenience polymorphic function to create an expression node 216 template <typename A0, typename A1 ... typename AN> 217 result_of::make_name<A0, A1 ... AN> 218 make_name(A0 const & a0, A1 const & a1 ... AN const & an); 219 220This macros also adds a specialization for `meta_grammar::case_<tag::name>` to 221enable the rule for further use in actions. 222 223[heading Header] 224 225 #include <boost/phoenix/core/expression.hpp> 226 227[heading Example] 228 229The example from the previous section can be rewritten as: 230 231 BOOST_PHOENIX_DEFINE_EXPRESSION( 232 (plus) 233 , (meta_grammar) // Lhs 234 (meta_grammar) // Rhs 235 ) 236 237 template <typename Lhs, typename Rhs> 238 typename plus<Lhs, Rhs>::type 239 plus(Lhs const & lhs, Rhs const & rhs) 240 { 241 return expression::plus<Lhs, Rhs>::make(lhs, rhs); 242 } 243 244[endsect] 245 246[section BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG] 247 248[heading Description] 249 250`BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG` is a macro that can be used to generate all the 251necessary boilerplate to create Phoenix Expressions 252 253[heading Synopsis] 254 255 BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( 256 (namespace_seq)(name) 257 , (child_grammar0) 258 (child_grammar1) 259 ... 260 (child_grammarN) 261 , N 262 ) 263 264[heading Semantics] 265 266The above macro generates the necessary code for an expression `name` in 267namespace `namespace_seq`. `N` is the maximum number of variable children. 268All but the last elements in the grammar sequence are required children of 269the expression, and the last denotes a variable number of children. The number 270of children an expression of this kind can hold is therefor `N-1` plus the size of 271the sequence 272 273The macro should be used at global scope. `namespace_seq` shall be the sequence 274of namespaces under which the following symbols will be defined: 275 276 namespace tag 277 { 278 struct name; 279 } 280 281 namespace expression 282 { 283 template <typename A0, typename A1 ... typename AN> 284 struct name 285 : boost::phoenix::expr< 286 tag::name 287 , A0 288 , A1 289 ... 290 , AN 291 > 292 {}; 293 } 294 295 namespace rule 296 { 297 struct name 298 : expression::name< 299 child_grammar0 300 , child_grammar1 301 ... 302 , proto::vararg<child_grammarN> 303 > 304 {}; 305 } 306 307 namespace functional 308 { 309 struct make_name; // A polymorphic function object that can be called to create the expression node 310 } 311 312 namespace result_of 313 { 314 template <typename A0, typename A1 ... typename AN> 315 struct make_name; // The result type of the expression node 316 } 317 318 // convenience polymorphic function to create an expression node 319 template <typename A0, typename A1 ... typename AN> 320 result_of::make_name<A0, A1 ... AN> 321 make_name(A0 const & a0, A1 const & a1 ... AN const & an); 322 323This macros also adds a specialization for `meta_grammar::case_<tag::name>` to 324enable the rule for further use in actions. 325 326[heading Header] 327 328 #include <boost/phoenix/core/expression.hpp> 329 330[heading Example] 331 332 BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( 333 (boost)(phoenix)(mem_fun_ptr) 334 , (meta_grammar) // Pointer to Object 335 (meta_grammar) // Member pointer 336 (meta_grammar) // Variable number of arguments 337 , BOOST_PHOENIX_LIMIT 338 ) 339 340This defines the member function pointer operator expression as described in 341[link phoenix.modules.operator operators]. 342 343[endsect] 344 345[section BOOST_PHOENIX_DEFINE_EXPRESSION_EXT] 346 347[heading Description] 348 349`BOOST_PHOENIX_DEFINE_EXPRESSION_EXT` is a macro that can be used to generate all the 350necessary boilerplate to create Phoenix Expressions 351 352[heading Synopsis] 353 354 BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( 355 actor 356 , (namespace_seq)(name) 357 , (child_grammar0) 358 (child_grammar1) 359 ... 360 (child_grammarN) 361 , N 362 ) 363 364[heading Semantics] 365 366The above macro generates the necessary code for an expression `name` in 367namespace `namespace_seq`. The sequence of `(child_grammarN)` declares how many 368children the expression will have and what `proto::grammar` they match. 369 370The macro should be used at global scope. `namespace_seq` shall be the sequence 371of namespaces under which the following symbols will be defined: 372 373 namespace tag 374 { 375 struct name; 376 } 377 378 namespace expression 379 { 380 template <typename A0, typename A1 ... typename AN> 381 struct name 382 : boost::phoenix::expr_ext< 383 actor 384 , tag::name 385 , A0 386 , A1 387 ... 388 , AN 389 > 390 } 391 392 namespace rule 393 { 394 struct name 395 : boost::phoenix::expr< 396 child_grammar0 397 , child_grammar1 398 ... 399 , child_grammarN 400 > 401 {}; 402 } 403 404 namespace functional 405 { 406 struct make_name; // A polymorphic function object that can be called to create the expression node 407 } 408 409 namespace result_of 410 { 411 template <typename A0, typename A1 ... typename AN> 412 struct make_name; // The result type of the expression node 413 } 414 415 // convenience polymorphic function to create an expression node 416 template <typename A0, typename A1 ... typename AN> 417 result_of::make_name<A0, A1 ... AN> 418 make_name(A0 const & a0, A1 const & a1 ... AN const & an); 419 420This macros also adds a specialization for `meta_grammar::case_<tag::name>` to 421enable the rule for further use in actions. 422 423[heading Header] 424 425 #include <boost/phoenix/core/expression.hpp> 426 427[heading Example] 428 429 BOOST_PHOENIX_DEFINE_EXPRESSION_EXT( 430 if_actor 431 , (boost)(phoenix)(if_) 432 , (meta_grammar) // Cond 433 (meta_grammar) // Then 434 ) 435 436This defines the if_ expression. The custom actor defines `else_` as a member. 437 438[endsect] 439 440[section BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG] 441 442[heading Description] 443 444`BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG` is a macro that can be used to generate all the 445necessary boilerplate to create Phoenix Expressions 446 447[heading Synopsis] 448 449 BOOST_PHOENIX_DEFINE_EXPRESSION_EXT_VARARG( 450 actor 451 , (namespace_seq)(name) 452 , (child_grammar0) 453 (child_grammar1) 454 ... 455 (child_grammarN) 456 , N 457 ) 458 459[heading Semantics] 460 461The above macro generates the necessary code for an expression `name` in 462namespace `namespace_seq`. `N` is the maximum number of variable children. 463All but the last elements in the grammar sequence are required children of 464the expression, and the last denotes a variable number of children. The number 465of children an expression of this kind can hold is therefor `N-1` plus the size of 466the sequence 467 468The macro should be used at global scope. `namespace_seq` shall be the sequence 469of namespaces under which the following symbols will be defined: 470 471 namespace tag 472 { 473 struct name; 474 } 475 476 namespace expression 477 { 478 template <typename A0, typename A1 ... typename AN> 479 struct name 480 : boost::phoenix::expr_ext< 481 actor 482 , tag::name 483 , A0 484 , A1 485 ... 486 , AN 487 > 488 {}; 489 } 490 491 namespace rule 492 { 493 struct name 494 : expression::name< 495 child_grammar0 496 , child_grammar1 497 ... 498 , proto::vararg<child_grammarN> 499 > 500 {}; 501 } 502 503 namespace functional 504 { 505 struct make_name; // A polymorphic function object that can be called to create the expression node 506 } 507 508 namespace result_of 509 { 510 template <typename A0, typename A1 ... typename AN> 511 struct make_name; // The result type of the expression node 512 } 513 514 // convenience polymorphic function to create an expression node 515 template <typename A0, typename A1 ... typename AN> 516 result_of::make_name<A0, A1 ... AN> 517 make_name(A0 const & a0, A1 const & a1 ... AN const & an); 518 519This macros also adds a specialization for `meta_grammar::case_<tag::name>` to 520enable the rule for further use in actions. 521 522[heading Header] 523 524 #include <boost/phoenix/core/expression.hpp> 525 526[heading Example] 527 528TBD 529 530[endsect] 531 532[endsect] 533 534[endsect] 535