1[/============================================================================== 2 Copyright (C) 2001-2011 Hartmut Kaiser 3 Copyright (C) 2001-2011 Joel de Guzman 4 Copyright (C) 2009 Chris Hoeppler 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:confix Qi Confix Parser Directive] 11 12[heading Description] 13 14The __qi__ `confix` directive is a unary parser component allowing to embed a 15parser (the subject) inside an opening (the prefix) and a closing (the suffix): 16 17 confix(prefix, suffix)[subject] 18 19This results in a parser that is equivalent to the sequence 20 21 omit[prefix] >> subject >> omit[suffix] 22 23A simple example is a parser for non-nested comments which can now be written 24as: 25 26 confix("/*", "*/")[*(char_ - "*/")] // C style comment 27 confix("//", eol)[*(char_ - eol)] // C++ style comment 28 29Using the `confix` directive instead of the explicit sequence has the advantage 30of being able to encapsulate the prefix and the suffix into a separate construct. 31The following code snippet illustrates the idea: 32 33 namespace spirit = boost::spirit; 34 namespace repo = boost::spirit::repository; 35 36 // Define a metafunction allowing to compute the type 37 // of the confix() construct 38 template <typename Prefix, typename Suffix = Prefix> 39 struct confix_spec 40 { 41 typedef typename spirit::result_of::terminal< 42 repo::tag::confix(Prefix, Suffix) 43 >::type type; 44 }; 45 46 confix_spec<std::string>::type const c_comment = repo::confix("/*", "*/"); 47 confix_spec<std::string>::type const cpp_comment = repo::confix("//", "\n"); 48 49Now, the comment parsers can be written as 50 51 c_comment[*(char_ - "*/")] // C style comment 52 cpp_comment[*(char_ - eol)] // C++ style comment 53 54[note While the `confix_p(prefix, subject, suffix)` parser in __classic__ 55 was equivalent to the sequence `prefix >> *(subject - suffix) >> suffix, 56 the __qi__ `confix` directive will not perform this refactoring any more. 57 This simplifies the code and makes things more explicit.] 58 59[heading Header] 60 61 // forwards to <boost/spirit/repository/home/qi/directive/confix.hpp> 62 #include <boost/spirit/repository/include/qi_confix.hpp> 63 64[heading Synopsis] 65 66 confix(prefix, suffix)[subject] 67 68[heading Parameters] 69 70[table 71 [[Parameter] [Description]] 72 [[`prefix`] [The parser for the opening (the prefix).]] 73 [[`suffix`] [The parser for the ending (the suffix).]] 74 [[`subject`] [The parser for the input sequence between the 75 `prefix` and `suffix` parts.]] 76] 77 78All three parameters can be arbitrarily complex parsers themselves. 79 80[heading Attribute] 81 82The `confix` directive exposes the attribute type of its subject as its own 83attribute type. If the `subject` does not expose any attribute (the type is 84`unused_type`), then the `confix` does not expose any attribute either. 85 86 a: A, p: P, s: S: --> confix(p, s)[a]: A 87 88[note This notation is used all over the Spirit documentation and reads as: 89 Given, `a`, `p`, and `s` are parsers, and `A`, `P`, and `S` are the types 90 of their attributes, then the type of the attribute exposed by 91 `confix(p, s)[a]` will be `A`.] 92 93[heading Example] 94 95The following example shows simple use cases of the `confix` directive. We will 96illustrate its usage by generating parsers for different comment styles and 97for some simple tagged data (for the full example code see 98[@../../example/qi/confix.cpp confix.cpp]) 99 100[import ../../example/qi/confix.cpp] 101 102[heading Prerequisites] 103 104In addition to the main header file needed to include the core components 105implemented in __qi__ we add the header file needed for the new `confix` 106directive. 107 108[qi_confix_includes] 109 110In order to make the examples below more readable we import a number of 111elements into the current namespace: 112 113[qi_confix_using] 114 115[heading Parsing Different Comment Styles] 116 117We will show how to parse different comment styles. First we will parse 118a C++ comment: 119 120[qi_confix_cpp_comment] 121 122This function will obviously parse input such as "`// This is a comment \n `". 123Similarily parsing a 'C'-style comment proves to be straightforward: 124 125[qi_confix_c_comment] 126 127which again will be able to parse e.g. "`/* This is a comment */ `". 128 129[heading Parsing Tagged Data] 130 131Generating a parser that extracts the body from the HTML snippet "`<b>The Body</b>`" 132is not very hard, either: 133 134[qi_confix_tagged_data] 135 136 137[endsect] 138