1[/============================================================================== 2 Copyright (C) 2001-2011 Joel de Guzman 3 Copyright (C) 2001-2011 Hartmut Kaiser 4 Copyright (C) 2009 Francois Barel 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:subrule Karma subrules] 11 12[heading Description] 13 14The __karma__ `subrule` is a component allowing to create a named generator, and 15to refer to it by name -- much like rules and grammars. It is in fact a fully 16static version of the rule. 17 18The strength of subrules is performance. Replacing some rules with subrules 19can make a generator slightly faster (see 20[link spirit_repository.karma_components.nonterminal.subrule.performance Performance] 21below for measurements). The reason is that subrules allow aggressive inlining 22by the C++ compiler, whereas the implementation of rules is based on a virtual 23function call which, depending on the compiler, can have some run-time overhead 24and stop inlining. 25 26The weaknesses of subrules are: 27 28* subrules can only be defined and used within the same generator expression. A 29 subrule cannot be defined at one location, and then used in another location. 30* subrules put a massive strain on the C++ compiler. They increase compile 31 times and memory usage during compilation, and also increase the risk of 32 hitting compiler limits and/or bugs. 33 34[import ../../example/karma/calc2_ast_dump_sr.cpp] 35 36[calc2_ast_dump_sr_def] 37 38The example above can be found here: [@../../example/karma/calc2_ast_dump_sr.cpp] 39 40As shown in this code snippet (an extract from the calc2_ast_dump_sr example), 41subrules can be freely mixed with rules and grammars. Here, a group of 423 subrules (`ast_node`, `binary_node`, `unary_node`) is assigned to a rule (named 43`entry`). This means that parts of a generator can use subrules (typically 44the innermost, most performance-critical parts), whereas the rest can use 45rules and grammars. 46 47[heading Header] 48 49 // forwards to <boost/spirit/repository/home/karma/nonterminal/subrule.hpp> 50 #include <boost/spirit/repository/include/karma_subrule.hpp> 51 52[heading Synopsis (declaration)] 53 54 subrule<ID, A1, A2> sr(name); 55 56[heading Parameters (declaration)] 57 58[table 59 [[Parameter] [Description]] 60 [[`ID`] [Required numeric argument. Gives the subrule 61 a unique 'identification tag'.]] 62 [[`A1`, `A2`] [Optional types, can be specified in any order. 63 Can be one of 1. signature, 2. locals 64 (see rules reference for more information on 65 those parameters). 66 67 Note that the delimiter type need not be specified 68 in the parameters, unlike with grammars and rules. 69 Subrules will automatically use the delimiter type 70 which is in effect when they are invoked.]] 71 [[`name`] [Optional string. Gives the subrule a name, 72 useful for debugging and error handling.]] 73] 74 75[heading Synopsis (usage)] 76 77Subrules are defined and used within groups, typically (and by convention) 78enclosed inside parentheses. 79 80 // Group containing N subrules 81 ( 82 sr1 = expr1 83 , sr2 = expr2 84 , ... // Any number of subrules 85 } 86 87The IDs of all subrules defined within the same group must be different. It is 88an error to define several subrules with the same ID (or to define the same 89subrule multiple times) in the same group. 90 91 // Auto-subrules and inherited attributes 92 ( 93 srA %= exprA << srB << srC(c1, c2, ...) // Arguments to subrule srC 94 , srB %= exprB 95 , srC = exprC 96 , ... 97 )(a1, a2, ...) // Arguments to group, i.e. to start subrule srA 98 99[heading Parameters (usage)] 100 101[table 102 [[Parameter] [Description]] 103 [[`sr1`, `sr2`] [Subrules with different IDs.]] 104 [[`expr1`, `expr2`] [Generator expressions. Can include `sr1` and `sr2`, 105 as well as any other valid generator expressions.]] 106 [[`srA`] [Subrule with a synthesized attribute and inherited 107 attributes.]] 108 [[`srB`] [Subrule with a synthesized attribute.]] 109 [[`srC`] [Subrule with inherited attributes.]] 110 [[`exprA`, `exprB`, `exprC`] 111 [Generator expressions.]] 112 [[`a1`, `a2`] [Arguments passed to the subrule group. They are 113 passed as inherited attributes to the group's 114 start subrule, `srA`.]] 115 [[`c1`, `c2`] [Arguments passed as inherited attributes to 116 subrule `srC`.]] 117] 118 119[heading Groups] 120 121A subrule group (a set of subrule definitions) is a generator, which can be 122used anywhere in a generator expression (in assignments to rules, as well as 123directly in arguments to functions such as `generate`). 124In a group, generation proceeds from the start subrule, which is the first 125(topmost) subrule defined in that group. In the two groups in the synopsis 126above, `sr1` and `srA` are the start subrules respectively -- for example 127when the first subrule group is called forth, the `sr1` subrule is called. 128 129A subrule can only be used in a group which defines it. Groups can be viewed 130as scopes: a definition of a subrule is limited to its enclosing group. 131 132 rule<outiter_type> r1, r2, r3; 133 subrule<1> sr1; 134 subrule<2> sr2; 135 136 r1 = 137 ( sr1 = 'a' << space ) // First group in r1. 138 << ( sr2 = +sr1 ) // Second group in r1. 139 // ^^^ 140 // DOES NOT COMPILE: sr1 is not defined in this 141 // second group, it cannot be used here (its 142 // previous definition is out of scope). 143 ; 144 145 r2 = 146 ( sr1 = 'a' << space ) // Only group in r2. 147 << sr1 148 // ^^^ 149 // DOES NOT COMPILE: not in a subrule group, 150 // sr1 cannot be used here (here too, its 151 // previous definition is out of scope). 152 ; 153 154 r3 = 155 ( sr1 = space << 'x' ) // Another group. The same subrule `sr1` 156 // can have another, independent 157 // definition in this group. 158 ; 159 160[heading Attributes] 161 162A subrule has the same behavior as a rule with respect to attributes. In 163particular: 164 165* the type of its synthesized attribute is the one specified in the 166 subrule's signature, if any. Otherwise it is `unused_type`. 167* the types of its inherited attributes are the ones specified in the 168 subrule's signature, if any. Otherwise the subrule has no inherited 169 attributes. 170* an auto-subrule can be defined by assigning it with the `%=` syntax. 171 In this case, the subrule's synthesized attribute is automatically 172 propagated to the RHS generator's attribute. 173* the Phoenix placeholders `_val`, `_r1`, `_r2`, ... are available to 174 refer to the subrule's synthesized and inherited attributes, if present. 175 176[heading Locals] 177 178A subrule has the same behavior as a rule with respect to locals. In 179particular, the Phoenix placeholders `_a`, `_b`, ... are available to 180refer to the subrule's locals, if present. 181 182[heading Example] 183 184[import ../../example/karma/mini_xml_karma_sr.cpp] 185 186Some includes: 187 188[mini_xml_karma_sr_includes] 189 190Some using declarations: 191 192[mini_xml_karma_sr_using] 193 194A grammar containing only one rule, defined with a group of 2 subrules: 195 196[mini_xml_karma_sr_grammar] 197 198The definitions of the `mini_xml` and `mini_xml_node` data structures 199are not shown here. The full example above can be found here: 200[@../../example/karma/mini_xml_karma_sr.cpp] 201 202[heading Performance] 203 204For comparison of run-time and compile-time performance when using subrules, 205please see the 206[link spirit_repository.qi_components.nonterminal.subrule.performance Performance] 207section of __qi__ subrules (the implementation of __karma__ and __qi__ subrules 208is very similar, so performance is very similar too). 209 210[heading Notes] 211 212Subrules push the C++ compiler hard. A group of subrules is a single C++ 213expression. Current C++ compilers cannot handle very complex expressions very 214well. One restricting factor is the typical compiler's limit on template 215recursion depth. Some, but not all, compilers allow this limit to be 216configured. 217 218g++'s maximum can be set using a compiler flag: `-ftemplate-depth`. Set this 219appropriately if you use relatively complex subrules. 220 221[endsect] 222