1 /* 2 * Created by Martin on 19/07/2017. 3 * 4 * Distributed under the Boost Software License, Version 1.0. (See accompanying 5 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 8 #include "catch_test_spec_parser.h" 9 10 namespace Catch { 11 TestSpecParser(ITagAliasRegistry const & tagAliases)12 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 13 parse(std::string const & arg)14 TestSpecParser& TestSpecParser::parse( std::string const& arg ) { 15 m_mode = None; 16 m_exclusion = false; 17 m_start = std::string::npos; 18 m_arg = m_tagAliases->expandAliases( arg ); 19 m_escapeChars.clear(); 20 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 21 visitChar( m_arg[m_pos] ); 22 if( m_mode == Name ) 23 addPattern<TestSpec::NamePattern>(); 24 return *this; 25 } testSpec()26 TestSpec TestSpecParser::testSpec() { 27 addFilter(); 28 return m_testSpec; 29 } 30 visitChar(char c)31 void TestSpecParser::visitChar( char c ) { 32 if( m_mode == None ) { 33 switch( c ) { 34 case ' ': return; 35 case '~': m_exclusion = true; return; 36 case '[': return startNewMode( Tag, ++m_pos ); 37 case '"': return startNewMode( QuotedName, ++m_pos ); 38 case '\\': return escape(); 39 default: startNewMode( Name, m_pos ); break; 40 } 41 } 42 if( m_mode == Name ) { 43 if( c == ',' ) { 44 addPattern<TestSpec::NamePattern>(); 45 addFilter(); 46 } 47 else if( c == '[' ) { 48 if( subString() == "exclude:" ) 49 m_exclusion = true; 50 else 51 addPattern<TestSpec::NamePattern>(); 52 startNewMode( Tag, ++m_pos ); 53 } 54 else if( c == '\\' ) 55 escape(); 56 } 57 else if( m_mode == EscapedName ) 58 m_mode = Name; 59 else if( m_mode == QuotedName && c == '"' ) 60 addPattern<TestSpec::NamePattern>(); 61 else if( m_mode == Tag && c == ']' ) 62 addPattern<TestSpec::TagPattern>(); 63 } startNewMode(Mode mode,std::size_t start)64 void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { 65 m_mode = mode; 66 m_start = start; 67 } escape()68 void TestSpecParser::escape() { 69 if( m_mode == None ) 70 m_start = m_pos; 71 m_mode = EscapedName; 72 m_escapeChars.push_back( m_pos ); 73 } subString() const74 std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } 75 addFilter()76 void TestSpecParser::addFilter() { 77 if( !m_currentFilter.m_patterns.empty() ) { 78 m_testSpec.m_filters.push_back( m_currentFilter ); 79 m_currentFilter = TestSpec::Filter(); 80 } 81 } 82 parseTestSpec(std::string const & arg)83 TestSpec parseTestSpec( std::string const& arg ) { 84 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 85 } 86 87 } // namespace Catch 88