| 5868 | namespace Catch { |
| 5869 | |
| 5870 | class TestSpecParser |
| 5871 | { |
| 5872 | enum Mode |
| 5873 | { |
| 5874 | None, |
| 5875 | Name, |
| 5876 | QuotedName, |
| 5877 | Tag, |
| 5878 | EscapedName |
| 5879 | }; |
| 5880 | Mode m_mode = None; |
| 5881 | bool m_exclusion = false; |
| 5882 | std::size_t m_start = std::string::npos, m_pos = 0; |
| 5883 | std::string m_arg; |
| 5884 | std::vector<std::size_t> m_escapeChars; |
| 5885 | TestSpec::Filter m_currentFilter; |
| 5886 | TestSpec m_testSpec; |
| 5887 | ITagAliasRegistry const* m_tagAliases = nullptr; |
| 5888 | |
| 5889 | public: |
| 5890 | TestSpecParser(ITagAliasRegistry const& tagAliases); |
| 5891 | |
| 5892 | TestSpecParser& parse(std::string const& arg); |
| 5893 | TestSpec testSpec(); |
| 5894 | |
| 5895 | private: |
| 5896 | void visitChar(char c); |
| 5897 | void startNewMode(Mode mode, std::size_t start); |
| 5898 | void escape(); |
| 5899 | std::string subString() const; |
| 5900 | |
| 5901 | template<typename T> |
| 5902 | void addPattern() |
| 5903 | { |
| 5904 | std::string token = subString(); |
| 5905 | for (std::size_t i = 0; i < m_escapeChars.size(); ++i) |
| 5906 | token = token.substr(0, m_escapeChars[i] - m_start - i) + token.substr(m_escapeChars[i] - m_start - i + 1); |
| 5907 | m_escapeChars.clear(); |
| 5908 | if (startsWith(token, "exclude:")) |
| 5909 | { |
| 5910 | m_exclusion = true; |
| 5911 | token = token.substr(8); |
| 5912 | } |
| 5913 | if (!token.empty()) |
| 5914 | { |
| 5915 | TestSpec::PatternPtr pattern = std::make_shared<T>(token); |
| 5916 | if (m_exclusion) |
| 5917 | pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); |
| 5918 | m_currentFilter.m_patterns.push_back(pattern); |
| 5919 | } |
| 5920 | m_exclusion = false; |
| 5921 | m_mode = None; |
| 5922 | } |
| 5923 | |
| 5924 | void addFilter(); |
| 5925 | }; |
| 5926 | TestSpec parseTestSpec(std::string const& arg); |
| 5927 | |