regeximpl.h 4.4 KB
Newer Older
1
2
#pragma once

3
4
5
6
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "stream.h"
#include "stringsource.h"
#include "streamcharsource.h"

namespace YAML
{
	// query matches
	inline bool RegEx::Matches(char ch) const {
		std::string str;
		str += ch;
		return Matches(str);
	}
	
	inline bool RegEx::Matches(const std::string& str) const {
		return Match(str) >= 0;
	}
	
	inline bool RegEx::Matches(const Stream& in) const {
		return Match(in) >= 0;
	}

	template <typename Source>
	inline bool RegEx::Matches(const Source& source) const {
		return Match(source) >= 0;
	}

	// Match
	// . Matches the given string against this regular expression.
	// . Returns the number of characters matched.
	// . Returns -1 if no characters were matched (the reason for
	//   not returning zero is that we may have an empty regex
	//   which is ALWAYS successful at matching zero characters).
	// . REMEMBER that we only match from the start of the buffer!	
	inline int RegEx::Match(const std::string& str) const
	{
		StringCharSource source(str.c_str(), str.size());
		return Match(source);
	}
	
	inline int RegEx::Match(const Stream& in) const
	{
		StreamCharSource source(in);
		return Match(source);
	}

	template <typename Source>
	inline bool RegEx::IsValidSource(const Source& source) const
	{
		return source;
	}
	
	template<>
	inline bool RegEx::IsValidSource<StringCharSource>(const StringCharSource&source) const
	{
		return source || m_op == REGEX_EMPTY;
	}

	template <typename Source>
	inline int RegEx::Match(const Source& source) const
	{
		return IsValidSource(source) ? MatchUnchecked(source) : -1;
	}
	
	template <typename Source>
	inline int RegEx::MatchUnchecked(const Source& source) const
	{
		switch(m_op) {
			case REGEX_EMPTY:
				return MatchOpEmpty(source);
			case REGEX_MATCH:
				return MatchOpMatch(source);
			case REGEX_RANGE:
				return MatchOpRange(source);
			case REGEX_OR:
				return MatchOpOr(source);
			case REGEX_AND:
				return MatchOpAnd(source);
			case REGEX_NOT:
				return MatchOpNot(source);
			case REGEX_SEQ:
				return MatchOpSeq(source);
		}
		
		return -1;
	}

	//////////////////////////////////////////////////////////////////////////////
	// Operators
	// Note: the convention MatchOp*<Source> is that we can assume IsSourceValid(source).
	//       So we do all our checks *before* we call these functions
	
	// EmptyOperator
	template <typename Source>
	inline int RegEx::MatchOpEmpty(const Source& source) const {
		return source[0] == Stream::eof() ? 0 : -1;
	}
	
	template <>
	inline int RegEx::MatchOpEmpty<StringCharSource>(const StringCharSource& source) const {
		return !source ? 0 : -1;  // the empty regex only is successful on the empty string
	}

	// MatchOperator
	template <typename Source>
	inline int RegEx::MatchOpMatch(const Source& source) const {
		if(source[0] != m_a)
			return -1;
		return 1;
	}
	
	// RangeOperator
	template <typename Source>
	inline int RegEx::MatchOpRange(const Source& source) const {
		if(m_a > source[0] || m_z < source[0])
			return -1;
		return 1;
	}
	
	// OrOperator
	template <typename Source>
	inline int RegEx::MatchOpOr(const Source& source) const {
128
		for(std::size_t i=0;i<m_params.size();i++) {
129
130
131
132
133
134
135
136
137
138
139
140
141
142
			int n = m_params[i].MatchUnchecked(source);
			if(n >= 0)
				return n;
		}
		return -1;
	}
	
	// AndOperator
	// Note: 'AND' is a little funny, since we may be required to match things
	//       of different lengths. If we find a match, we return the length of
	//       the FIRST entry on the list.
	template <typename Source>
	inline int RegEx::MatchOpAnd(const Source& source) const {
		int first = -1;
143
		for(std::size_t i=0;i<m_params.size();i++) {
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
			int n = m_params[i].MatchUnchecked(source);
			if(n == -1)
				return -1;
			if(i == 0)
				first = n;
		}
		return first;
	}
	
	// NotOperator
	template <typename Source>
	inline int RegEx::MatchOpNot(const Source& source) const {
		if(m_params.empty())
			return -1;
		if(m_params[0].MatchUnchecked(source) >= 0)
			return -1;
		return 1;
	}
	
	// SeqOperator
	template <typename Source>
	inline int RegEx::MatchOpSeq(const Source& source) const {
		int offset = 0;
167
		for(std::size_t i=0;i<m_params.size();i++) {
168
169
170
171
172
173
174
175
176
			int n = m_params[i].Match(source + offset); // note Match, not MatchUnchecked because we need to check validity after the offset
			if(n == -1)
				return -1;
			offset += n;
		}
		
		return offset;
	}
}
177
178

#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66