| 6174 | using ParserBase::parse; |
| 6175 | |
| 6176 | auto parse(std::string const &exeName, TokenStream const &tokens) const -> InternalParseResult override { |
| 6177 | |
| 6178 | struct ParserInfo { |
| 6179 | ParserBase const *parser = nullptr; |
| 6180 | size_t count = 0; |
| 6181 | }; |
| 6182 | const size_t totalParsers = m_options.size() + m_args.size(); |
| 6183 | assert(totalParsers < 512); |
| 6184 | // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do |
| 6185 | ParserInfo parseInfos[512]; |
| 6186 | |
| 6187 | { |
| 6188 | size_t i = 0; |
| 6189 | for (auto const &opt : m_options) |
| 6190 | parseInfos[i++].parser = &opt; |
| 6191 | for (auto const &arg : m_args) |
| 6192 | parseInfos[i++].parser = &arg; |
| 6193 | } |
| 6194 | |
| 6195 | m_exeName.set(exeName); |
| 6196 | |
| 6197 | auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); |
| 6198 | while (result.value().remainingTokens()) { |
| 6199 | bool tokenParsed = false; |
| 6200 | |
| 6201 | for (size_t i = 0; i < totalParsers; ++i) { |
| 6202 | auto &parseInfo = parseInfos[i]; |
| 6203 | if (parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality()) { |
| 6204 | result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); |
| 6205 | if (!result) |
| 6206 | return result; |
| 6207 | if (result.value().type() != ParseResultType::NoMatch) { |
| 6208 | tokenParsed = true; |
| 6209 | ++parseInfo.count; |
| 6210 | break; |
| 6211 | } |
| 6212 | } |
| 6213 | } |
| 6214 | |
| 6215 | if (result.value().type() == ParseResultType::ShortCircuitAll) |
| 6216 | return result; |
| 6217 | if (!tokenParsed) |
| 6218 | return InternalParseResult::runtimeError("Unrecognised token: " + result.value().remainingTokens()->token); |
| 6219 | } |
| 6220 | // !TBD Check missing required options |
| 6221 | return result; |
| 6222 | } |
| 6223 | }; |
| 6224 | |
| 6225 | template <typename DerivedT> |
nothing calls this directly
no test coverage detected