| 7704 | using ParserBase::parse; |
| 7705 | |
| 7706 | auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { |
| 7707 | |
| 7708 | struct ParserInfo { |
| 7709 | ParserBase const* parser = nullptr; |
| 7710 | size_t count = 0; |
| 7711 | }; |
| 7712 | const size_t totalParsers = m_options.size() + m_args.size(); |
| 7713 | assert( totalParsers < 512 ); |
| 7714 | // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do |
| 7715 | ParserInfo parseInfos[512]; |
| 7716 | |
| 7717 | { |
| 7718 | size_t i = 0; |
| 7719 | for (auto const &opt : m_options) parseInfos[i++].parser = &opt; |
| 7720 | for (auto const &arg : m_args) parseInfos[i++].parser = &arg; |
| 7721 | } |
| 7722 | |
| 7723 | m_exeName.set( exeName ); |
| 7724 | |
| 7725 | auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); |
| 7726 | while( result.value().remainingTokens() ) { |
| 7727 | bool tokenParsed = false; |
| 7728 | |
| 7729 | for( size_t i = 0; i < totalParsers; ++i ) { |
| 7730 | auto& parseInfo = parseInfos[i]; |
| 7731 | if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { |
| 7732 | result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); |
| 7733 | if (!result) |
| 7734 | return result; |
| 7735 | if (result.value().type() != ParseResultType::NoMatch) { |
| 7736 | tokenParsed = true; |
| 7737 | ++parseInfo.count; |
| 7738 | break; |
| 7739 | } |
| 7740 | } |
| 7741 | } |
| 7742 | |
| 7743 | if( result.value().type() == ParseResultType::ShortCircuitAll ) |
| 7744 | return result; |
| 7745 | if( !tokenParsed ) |
| 7746 | return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); |
| 7747 | } |
| 7748 | // !TBD Check missing required options |
| 7749 | return result; |
| 7750 | } |
| 7751 | }; |
| 7752 | |
| 7753 | template<typename DerivedT> |
nothing calls this directly
no test coverage detected