| 4268 | namespace Catch { |
| 4269 | |
| 4270 | class TestSpecParser { |
| 4271 | enum Mode{ None, Name, QuotedName, Tag, EscapedName }; |
| 4272 | Mode m_mode = None; |
| 4273 | bool m_exclusion = false; |
| 4274 | std::size_t m_start = std::string::npos, m_pos = 0; |
| 4275 | std::string m_arg; |
| 4276 | std::vector<std::size_t> m_escapeChars; |
| 4277 | TestSpec::Filter m_currentFilter; |
| 4278 | TestSpec m_testSpec; |
| 4279 | ITagAliasRegistry const* m_tagAliases = nullptr; |
| 4280 | |
| 4281 | public: |
| 4282 | TestSpecParser( ITagAliasRegistry const& tagAliases ); |
| 4283 | |
| 4284 | TestSpecParser& parse( std::string const& arg ); |
| 4285 | TestSpec testSpec(); |
| 4286 | |
| 4287 | private: |
| 4288 | void visitChar( char c ); |
| 4289 | void startNewMode( Mode mode, std::size_t start ); |
| 4290 | void escape(); |
| 4291 | std::string subString() const; |
| 4292 | |
| 4293 | template<typename T> |
| 4294 | void addPattern() { |
| 4295 | std::string token = subString(); |
| 4296 | for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) |
| 4297 | token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); |
| 4298 | m_escapeChars.clear(); |
| 4299 | if( startsWith( token, "exclude:" ) ) { |
| 4300 | m_exclusion = true; |
| 4301 | token = token.substr( 8 ); |
| 4302 | } |
| 4303 | if( !token.empty() ) { |
| 4304 | TestSpec::PatternPtr pattern = std::make_shared<T>( token ); |
| 4305 | if( m_exclusion ) |
| 4306 | pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern ); |
| 4307 | m_currentFilter.m_patterns.push_back( pattern ); |
| 4308 | } |
| 4309 | m_exclusion = false; |
| 4310 | m_mode = None; |
| 4311 | } |
| 4312 | |
| 4313 | void addFilter(); |
| 4314 | }; |
| 4315 | TestSpec parseTestSpec( std::string const& arg ); |
| 4316 | |
| 4317 | } // namespace Catch |