| 4599 | namespace Catch { |
| 4600 | |
| 4601 | class TestSpecParser { |
| 4602 | enum Mode{ None, Name, QuotedName, Tag, EscapedName }; |
| 4603 | Mode m_mode = None; |
| 4604 | bool m_exclusion = false; |
| 4605 | std::size_t m_start = std::string::npos, m_pos = 0; |
| 4606 | std::string m_arg; |
| 4607 | std::vector<std::size_t> m_escapeChars; |
| 4608 | TestSpec::Filter m_currentFilter; |
| 4609 | TestSpec m_testSpec; |
| 4610 | ITagAliasRegistry const* m_tagAliases = nullptr; |
| 4611 | |
| 4612 | public: |
| 4613 | TestSpecParser( ITagAliasRegistry const& tagAliases ); |
| 4614 | |
| 4615 | TestSpecParser& parse( std::string const& arg ); |
| 4616 | TestSpec testSpec(); |
| 4617 | |
| 4618 | private: |
| 4619 | void visitChar( char c ); |
| 4620 | void startNewMode( Mode mode, std::size_t start ); |
| 4621 | void escape(); |
| 4622 | std::string subString() const; |
| 4623 | |
| 4624 | template<typename T> |
| 4625 | void addPattern() { |
| 4626 | std::string token = subString(); |
| 4627 | for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) |
| 4628 | token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); |
| 4629 | m_escapeChars.clear(); |
| 4630 | if( startsWith( token, "exclude:" ) ) { |
| 4631 | m_exclusion = true; |
| 4632 | token = token.substr( 8 ); |
| 4633 | } |
| 4634 | if( !token.empty() ) { |
| 4635 | TestSpec::PatternPtr pattern = std::make_shared<T>( token ); |
| 4636 | if( m_exclusion ) |
| 4637 | pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern ); |
| 4638 | m_currentFilter.m_patterns.emplace_back( pattern ); |
| 4639 | } |
| 4640 | m_exclusion = false; |
| 4641 | m_mode = None; |
| 4642 | } |
| 4643 | |
| 4644 | void addFilter(); |
| 4645 | }; |
| 4646 | TestSpec parseTestSpec( std::string const& arg ); |
| 4647 | |
| 4648 | } // namespace Catch |