| 3186 | namespace Catch { |
| 3187 | |
| 3188 | class TestSpecParser { |
| 3189 | enum Mode{ None, Name, QuotedName, Tag, EscapedName }; |
| 3190 | Mode m_mode = None; |
| 3191 | bool m_exclusion = false; |
| 3192 | std::size_t m_start = std::string::npos, m_pos = 0; |
| 3193 | std::string m_arg; |
| 3194 | std::vector<std::size_t> m_escapeChars; |
| 3195 | TestSpec::Filter m_currentFilter; |
| 3196 | TestSpec m_testSpec; |
| 3197 | ITagAliasRegistry const* m_tagAliases = nullptr; |
| 3198 | |
| 3199 | public: |
| 3200 | TestSpecParser( ITagAliasRegistry const& tagAliases ); |
| 3201 | |
| 3202 | TestSpecParser& parse( std::string const& arg ); |
| 3203 | TestSpec testSpec(); |
| 3204 | |
| 3205 | private: |
| 3206 | void visitChar( char c ); |
| 3207 | void startNewMode( Mode mode, std::size_t start ); |
| 3208 | void escape(); |
| 3209 | std::string subString() const; |
| 3210 | |
| 3211 | template<typename T> |
| 3212 | void addPattern() { |
| 3213 | std::string token = subString(); |
| 3214 | for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) |
| 3215 | token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); |
| 3216 | m_escapeChars.clear(); |
| 3217 | if( startsWith( token, "exclude:" ) ) { |
| 3218 | m_exclusion = true; |
| 3219 | token = token.substr( 8 ); |
| 3220 | } |
| 3221 | if( !token.empty() ) { |
| 3222 | TestSpec::PatternPtr pattern = std::make_shared<T>( token ); |
| 3223 | if( m_exclusion ) |
| 3224 | pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern ); |
| 3225 | m_currentFilter.m_patterns.push_back( pattern ); |
| 3226 | } |
| 3227 | m_exclusion = false; |
| 3228 | m_mode = None; |
| 3229 | } |
| 3230 | |
| 3231 | void addFilter(); |
| 3232 | }; |
| 3233 | TestSpec parseTestSpec( std::string const& arg ); |
| 3234 | |
| 3235 | } // namespace Catch |