| 9598 | using ParserBase::parse; |
| 9599 | |
| 9600 | auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { |
| 9601 | |
| 9602 | struct ParserInfo { |
| 9603 | ParserBase const* parser = nullptr; |
| 9604 | size_t count = 0; |
| 9605 | }; |
| 9606 | const size_t totalParsers = m_options.size() + m_args.size(); |
| 9607 | assert( totalParsers < 512 ); |
| 9608 | // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do |
| 9609 | ParserInfo parseInfos[512]; |
| 9610 | |
| 9611 | { |
| 9612 | size_t i = 0; |
| 9613 | for (auto const &opt : m_options) parseInfos[i++].parser = &opt; |
| 9614 | for (auto const &arg : m_args) parseInfos[i++].parser = &arg; |
| 9615 | } |
| 9616 | |
| 9617 | m_exeName.set( exeName ); |
| 9618 | |
| 9619 | auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); |
| 9620 | while( result.value().remainingTokens() ) { |
| 9621 | bool tokenParsed = false; |
| 9622 | |
| 9623 | for( size_t i = 0; i < totalParsers; ++i ) { |
| 9624 | auto& parseInfo = parseInfos[i]; |
| 9625 | if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { |
| 9626 | result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); |
| 9627 | if (!result) |
| 9628 | return result; |
| 9629 | if (result.value().type() != ParseResultType::NoMatch) { |
| 9630 | tokenParsed = true; |
| 9631 | ++parseInfo.count; |
| 9632 | break; |
| 9633 | } |
| 9634 | } |
| 9635 | } |
| 9636 | |
| 9637 | if( result.value().type() == ParseResultType::ShortCircuitAll ) |
| 9638 | return result; |
| 9639 | if( !tokenParsed ) |
| 9640 | return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); |
| 9641 | } |
| 9642 | // !TBD Check missing required options |
| 9643 | return result; |
| 9644 | } |
| 9645 | }; |
| 9646 | |
| 9647 | template<typename DerivedT> |
nothing calls this directly
no test coverage detected