| 163 | } |
| 164 | |
| 165 | static std::vector<std::string> parse_section(std::string const& name, std::string const& source) { |
| 166 | // ECMAScript regex only has "?=" for a non-matching lookahead. In order to make sure we always have |
| 167 | // a newline to anchor our matching, we have to avoid matching the final newline of each grouping. |
| 168 | // Therefore, our regex is adjusted from the docopt Python one to use ?= to match the newlines before |
| 169 | // the following lines, rather than after. |
| 170 | std::regex const re_section_pattern { |
| 171 | "(?:^|\\n)" // anchored at a linebreak (or start of string) |
| 172 | "(" |
| 173 | "[^\\n]*" + name + "[^\\n]*(?=\\n?)" // a line that contains the name |
| 174 | "(?:\\n[ \\t].*?(?=\\n|$))*" // followed by any number of lines that are indented |
| 175 | ")", |
| 176 | std::regex::icase |
| 177 | }; |
| 178 | |
| 179 | std::vector<std::string> ret; |
| 180 | std::for_each(std::sregex_iterator(source.begin(), source.end(), re_section_pattern), |
| 181 | std::sregex_iterator(), |
| 182 | [&](std::smatch const& match) |
| 183 | { |
| 184 | ret.push_back(trim(match[1].str())); |
| 185 | }); |
| 186 | |
| 187 | return ret; |
| 188 | } |
| 189 | |
| 190 | static bool is_argument_spec(std::string const& token) { |
| 191 | if (token.empty()) |
no test coverage detected