| 1 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 2 | // main.hpp | 
|---|
| 3 | // | 
|---|
| 4 | //  Copyright 2004 Eric Niebler. Distributed under the Boost | 
|---|
| 5 | //  Software License, Version 1.0. (See accompanying file | 
|---|
| 6 | //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 7 |  | 
|---|
| 8 | #include <iostream> | 
|---|
| 9 | #include <iomanip> | 
|---|
| 10 | #include <boost/xpressive/xpressive.hpp> | 
|---|
| 11 |  | 
|---|
| 12 | using namespace boost::xpressive; | 
|---|
| 13 |  | 
|---|
| 14 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 15 | // Displays nested results to std::cout with indenting | 
|---|
| 16 | // | 
|---|
| 17 | // Display a tree of nested results | 
|---|
| 18 | // | 
|---|
| 19 | // Here is a helper class to demonstrate how you might display a tree of nested results: | 
|---|
| 20 | struct output_nested_results | 
|---|
| 21 | { | 
|---|
| 22 |     int tabs_; | 
|---|
| 23 |  | 
|---|
| 24 |     output_nested_results(int tabs = 0) | 
|---|
| 25 |       : tabs_(tabs) | 
|---|
| 26 |     { | 
|---|
| 27 |     } | 
|---|
| 28 |  | 
|---|
| 29 |     template< typename BidiIterT > | 
|---|
| 30 |     void operator ()( match_results< BidiIterT > const &what ) const | 
|---|
| 31 |     { | 
|---|
| 32 |         // first, do some indenting | 
|---|
| 33 |         typedef typename std::iterator_traits< BidiIterT >::value_type char_type; | 
|---|
| 34 |         char_type space_ch = char_type(' '); | 
|---|
| 35 |         std::fill_n( std::ostream_iterator<char_type>( std::cout ), tabs_ * 4, space_ch ); | 
|---|
| 36 |  | 
|---|
| 37 |         // output the match | 
|---|
| 38 |         std::cout << what[0] << '\n'; | 
|---|
| 39 |  | 
|---|
| 40 |         // output any nested matches | 
|---|
| 41 |         std::for_each( | 
|---|
| 42 |             what.nested_results().begin(), | 
|---|
| 43 |             what.nested_results().end(), | 
|---|
| 44 |             output_nested_results( tabs_ + 1 ) ); | 
|---|
| 45 |     } | 
|---|
| 46 | }; | 
|---|
| 47 |  | 
|---|
| 48 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 49 | // See if a whole string matches a regex | 
|---|
| 50 | // | 
|---|
| 51 | // This program outputs the following: | 
|---|
| 52 | // | 
|---|
| 53 | // hello world! | 
|---|
| 54 | // hello | 
|---|
| 55 | // world | 
|---|
| 56 |  | 
|---|
| 57 | void example1() | 
|---|
| 58 | { | 
|---|
| 59 |     std::string hello( "hello world!" ); | 
|---|
| 60 |  | 
|---|
| 61 |     sregex rex = sregex::compile( "(\\w+) (\\w+)!" ); | 
|---|
| 62 |     smatch what; | 
|---|
| 63 |  | 
|---|
| 64 |     if( regex_match( hello, what, rex ) ) | 
|---|
| 65 |     { | 
|---|
| 66 |         std::cout << what[0] << '\n'; // whole match | 
|---|
| 67 |         std::cout << what[1] << '\n'; // first capture | 
|---|
| 68 |         std::cout << what[2] << '\n'; // second capture | 
|---|
| 69 |     } | 
|---|
| 70 | } | 
|---|
| 71 |  | 
|---|
| 72 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 73 | // See if a string contains a sub-string that matches a regex | 
|---|
| 74 | // | 
|---|
| 75 | // Notice in this example how we use custom mark_tags to make the pattern | 
|---|
| 76 | // more readable. We can use the mark_tags later to index into the match_results<>. | 
|---|
| 77 | // | 
|---|
| 78 | // This program outputs the following: | 
|---|
| 79 | //  | 
|---|
| 80 | // 5/30/1973 | 
|---|
| 81 | // 30 | 
|---|
| 82 | // 5 | 
|---|
| 83 | // 1973 | 
|---|
| 84 | // / | 
|---|
| 85 |  | 
|---|
| 86 | void example2() | 
|---|
| 87 | { | 
|---|
| 88 |     char const *str = "I was born on 5/30/1973 at 7am."; | 
|---|
| 89 |  | 
|---|
| 90 |     // define some custom mark_tags with names more meaningful than s1, s2, etc. | 
|---|
| 91 |     mark_tag day(1), month(2), year(3), delim(4); | 
|---|
| 92 |  | 
|---|
| 93 |     // this regex finds a date | 
|---|
| 94 |     cregex date = (month= repeat<1,2>(_d))           // find the month ... | 
|---|
| 95 |                >> (delim= (set= '/','-'))            // followed by a delimiter ... | 
|---|
| 96 |                >> (day=   repeat<1,2>(_d)) >> delim  // and a day followed by the same delimiter ... | 
|---|
| 97 |                >> (year=  repeat<1,2>(_d >> _d));    // and the year. | 
|---|
| 98 |  | 
|---|
| 99 |     cmatch what; | 
|---|
| 100 |  | 
|---|
| 101 |     if( regex_search( str, what, date ) ) | 
|---|
| 102 |     { | 
|---|
| 103 |         std::cout << what[0]     << '\n'; // whole match | 
|---|
| 104 |         std::cout << what[day]   << '\n'; // the day | 
|---|
| 105 |         std::cout << what[month] << '\n'; // the month | 
|---|
| 106 |         std::cout << what[year]  << '\n'; // the year | 
|---|
| 107 |         std::cout << what[delim] << '\n'; // the delimiter | 
|---|
| 108 |     } | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 112 | // Replace all sub-strings that match a regex | 
|---|
| 113 | //  | 
|---|
| 114 | // The following program finds dates in a string and marks them up with pseudo-HTML. | 
|---|
| 115 | // | 
|---|
| 116 | // This program outputs the following: | 
|---|
| 117 | //  | 
|---|
| 118 | // I was born on <date>5/30/1973</date> at 7am. | 
|---|
| 119 |  | 
|---|
| 120 | void example3() | 
|---|
| 121 | { | 
|---|
| 122 |     std::string str( "I was born on 5/30/1973 at 7am." ); | 
|---|
| 123 |  | 
|---|
| 124 |     // essentially the same regex as in the previous example, but using a dynamic regex | 
|---|
| 125 |     sregex date = sregex::compile( "(\\d{1,2})([/-])(\\d{1,2})\\2((?:\\d{2}){1,2})" ); | 
|---|
| 126 |  | 
|---|
| 127 |     // As in Perl, $& is a reference to the sub-string that matched the regex | 
|---|
| 128 |     std::string format( "<date>$&</date>" ); | 
|---|
| 129 |  | 
|---|
| 130 |     str = regex_replace( str, date, format ); | 
|---|
| 131 |     std::cout << str << '\n'; | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 135 | // Find all the sub-strings that match a regex and step through them one at a time | 
|---|
| 136 | //  | 
|---|
| 137 | // The following program finds the words in a wide-character string. It uses wsregex_iterator. | 
|---|
| 138 | // Notice that dereferencing a wsregex_iterator yields a wsmatch object. | 
|---|
| 139 | // | 
|---|
| 140 | // This program outputs the following: | 
|---|
| 141 | //  | 
|---|
| 142 | // This | 
|---|
| 143 | // is | 
|---|
| 144 | // his | 
|---|
| 145 | // face | 
|---|
| 146 |  | 
|---|
| 147 | void example4() | 
|---|
| 148 | { | 
|---|
| 149 |     #ifndef BOOST_XPRESSIVE_NO_WREGEX | 
|---|
| 150 |     std::wstring str( L"This is his face." ); | 
|---|
| 151 |  | 
|---|
| 152 |     // find a whole word | 
|---|
| 153 |     wsregex token = +alnum; | 
|---|
| 154 |  | 
|---|
| 155 |     wsregex_iterator cur( str.begin(), str.end(), token ); | 
|---|
| 156 |     wsregex_iterator end; | 
|---|
| 157 |  | 
|---|
| 158 |     for( ; cur != end; ++cur ) | 
|---|
| 159 |     { | 
|---|
| 160 |         wsmatch const &what = *cur; | 
|---|
| 161 |         std::wcout << what[0] << L'\n'; | 
|---|
| 162 |     } | 
|---|
| 163 |     #endif | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 167 | // Split a string into tokens that each match a regex | 
|---|
| 168 | // | 
|---|
| 169 | // The following program finds race times in a string and displays first the minutes | 
|---|
| 170 | // and then the seconds. It uses regex_token_iterator<>. | 
|---|
| 171 | // | 
|---|
| 172 | // This program outputs the following: | 
|---|
| 173 | // | 
|---|
| 174 | // 4 | 
|---|
| 175 | // 40 | 
|---|
| 176 | // 3 | 
|---|
| 177 | // 35 | 
|---|
| 178 | // 2 | 
|---|
| 179 | // 32 | 
|---|
| 180 |  | 
|---|
| 181 | void example5() | 
|---|
| 182 | { | 
|---|
| 183 |     std::string str( "Eric: 4:40, Karl: 3:35, Francesca: 2:32" ); | 
|---|
| 184 |  | 
|---|
| 185 |     // find a race time | 
|---|
| 186 |     sregex time = sregex::compile( "(\\d):(\\d\\d)" ); | 
|---|
| 187 |  | 
|---|
| 188 |     // for each match, the token iterator should first take the value of | 
|---|
| 189 |     // the first marked sub-expression followed by the value of the second | 
|---|
| 190 |     // marked sub-expression | 
|---|
| 191 |     int const subs[] = { 1, 2 }; | 
|---|
| 192 |  | 
|---|
| 193 |     sregex_token_iterator cur( str.begin(), str.end(), time, subs ); | 
|---|
| 194 |     sregex_token_iterator end; | 
|---|
| 195 |  | 
|---|
| 196 |     for( ; cur != end; ++cur ) | 
|---|
| 197 |     { | 
|---|
| 198 |         std::cout << *cur << '\n'; | 
|---|
| 199 |     } | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 203 | // Split a string using a regex as a delimiter | 
|---|
| 204 | // | 
|---|
| 205 | // The following program takes some text that has been marked up with html and strips | 
|---|
| 206 | // out the mark-up. It uses a regex that matches an HTML tag and a regex_token_iterator<> | 
|---|
| 207 | // that returns the parts of the string that do not match the regex. | 
|---|
| 208 | // | 
|---|
| 209 | // This program outputs the following: | 
|---|
| 210 | // | 
|---|
| 211 | // {Now }{is the time }{for all good men}{ to come to the aid of their}{ country.} | 
|---|
| 212 |  | 
|---|
| 213 | void example6() | 
|---|
| 214 | { | 
|---|
| 215 |     std::string str( "Now <bold>is the time <i>for all good men</i> to come to the aid of their</bold> country." ); | 
|---|
| 216 |  | 
|---|
| 217 |     // find a HTML tag | 
|---|
| 218 |     sregex html = '<' >> optional('/') >> +_w >> '>'; | 
|---|
| 219 |  | 
|---|
| 220 |     // the -1 below directs the token iterator to display the parts of | 
|---|
| 221 |     // the string that did NOT match the regular expression. | 
|---|
| 222 |     sregex_token_iterator cur( str.begin(), str.end(), html, -1 ); | 
|---|
| 223 |     sregex_token_iterator end; | 
|---|
| 224 |  | 
|---|
| 225 |     for( ; cur != end; ++cur ) | 
|---|
| 226 |     { | 
|---|
| 227 |         std::cout << '{' << *cur << '}'; | 
|---|
| 228 |     } | 
|---|
| 229 |     std::cout << '\n'; | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 233 | // main | 
|---|
| 234 | int main() | 
|---|
| 235 | { | 
|---|
| 236 |     std::cout << "\n\nExample 1:\n\n"; | 
|---|
| 237 |     example1(); | 
|---|
| 238 |  | 
|---|
| 239 |     std::cout << "\n\nExample 2:\n\n"; | 
|---|
| 240 |     example2(); | 
|---|
| 241 |  | 
|---|
| 242 |     std::cout << "\n\nExample 3:\n\n"; | 
|---|
| 243 |     example3(); | 
|---|
| 244 |  | 
|---|
| 245 |     std::cout << "\n\nExample 4:\n\n"; | 
|---|
| 246 |     example4(); | 
|---|
| 247 |  | 
|---|
| 248 |     std::cout << "\n\nExample 5:\n\n"; | 
|---|
| 249 |     example5(); | 
|---|
| 250 |  | 
|---|
| 251 |     std::cout << "\n\nExample 6:\n\n"; | 
|---|
| 252 |     example6(); | 
|---|
| 253 |  | 
|---|
| 254 |     std::cout << "\n\n" << std::flush; | 
|---|
| 255 |  | 
|---|
| 256 |     return 0; | 
|---|
| 257 | } | 
|---|