Generic algorithms to find patterns similar to regular expressions
Operators:
(Expression) * OneOrMore :
(Expression) * ZeroOrMore :
(Expression) * Optional :
! (Expression) : Not
(Left)&(Right) : And
(Left)|(Right) : Or
Val(iterator::value_type) : Matches this value
Range(begin, end) : Matches if the value is in the interval begin end
Sample
int main()
{
std::string s = "a 123 b 45.67 c" ;
using namespace PatternMatching;
find_replace(s,
Range('0', '9') * OneOrMore & ('.' & Range('0', '9') * OneOrMore) * Optional,
std::string("NUMBER"));
using namespace PatternMatching;
std::wstring ss = L"121.54";
Result r;
//number : digit+ ('.' digit+)?
std::wstring::iterator it = Match(ss.begin(), ss.end(),
Range(L'0', L'9') * OneOrMore & (L'.' & Range(L'0', L'9') * OneOrMore) * Optional, r);
if (r)
{
// std::wcout << *it;
}
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(4);
//while not 2 walk...
std::vector<int>::iterator it2 = Match(v.begin(), v.end(), ! Val(2) * ZeroOrMore, r);
if (it2 != v.begin())
{
std::cout << *it2;
}
std::vector<int>::iterator it3 = Find(v.begin(), v.end(), (Val(2) | Val(3)) * OneOrMore);
return 0;
}
Code ```cpp
// Copyright (C) 2009, Thiago Adams (thiago.adams@gmail.com) // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose.
namespace PatternMatching { enum Result { ResultFalse = 0, ResultTrue, ResultTrueOptional, ResultFalseOptional };
template<class Iterator, class Expression>
Iterator Match(const Iterator& begin,
const Iterator& end,
const Expression& expr,
Result& result)
{
return expr.Match(begin, end, result);
}
//especialization
template
template<class T>
struct ValT
{
T ch;
ValT(const T& c) : ch(c) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "ValT" << std::endl;
result = ResultFalse;
if (begin == end)
return begin;
result = (*begin == ch) ? ResultTrue : ResultFalse;
//if (result)
//{
// return begin;// + 1;
//}
return begin;
}
};
template <class T>
ValT<T> Val(const T& v)
{
return v;
}
template<class T>
struct RangeT
{
T m_begin;
T m_end;
RangeT(T b, T e) : m_begin(b), m_end(e) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "Range" << std::endl;
result = ResultFalse;
if (begin == end)
return begin;
if ((*begin >= m_begin) && (*begin <= m_end))
result = ResultTrue;
else
result = ResultFalse;
//if (result)
//{
// return begin ;//+ 1;
//}
return begin;
}
};
template <class T>
RangeT<T> Range(const T& begin, const T& end)
{
return RangeT<T>(begin, end);
}
template<class Expr>
struct NotExpression
{
Expr exp;
NotExpression(const Expr& ll) : exp(ll) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "Not" << std::endl;
if (begin == end)
return begin;
Iterator it = PatternMatching::Match(begin, end, exp, result);
if (result == ResultFalse)
{
result = ResultTrue;
return begin;
}
else
{
result = ResultFalse;
}
return it;
}
};
template<class Expr>
NotExpression<Expr> operator!(const Expr& a)
{
return NotExpression<Expr>(a);
}
enum ZeroOrMoreT {ZeroOrMore};
template <class Expr>
struct ZeroOrMoreExpression
{
Expr exp;
ZeroOrMoreExpression(const Expr& e) : exp(e) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "ZeroOrMore" << std::endl;
result = ResultFalse;
if (begin == end)
return begin;
Iterator it(begin);
result = ResultTrue;
while (result == ResultTrue)
{
Result r;
Iterator it2 = PatternMatching::Match(it, end, exp, r);
if (r == ResultFalse)
break;
it++;//passa p frente
it = it2;
}
return it;
}
};
enum OneOrMoreT {OneOrMore};
template <class Expr>
struct OneOrMoreExpression
{
Expr exp;
OneOrMoreExpression(const Expr& e) : exp(e) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "OneOrMore" << std::endl;
result = ResultFalse;
if (begin == end)
return begin;
Iterator it(begin);
it = PatternMatching::Match(begin, end, exp, result);
if (result == ResultFalse)
return begin;
result = ResultTrue;
Iterator it2 = it;
it2++;//passa p frente
for (;it2 != end;)
{
Result r2;
it2 = PatternMatching::Match(it2, end, exp, r2);
if (r2 == ResultFalse)
break;
result = ResultTrue;
it = it2;
if (it2 == end)
break;
it2++;//passa p frente
}
return it;
}
};
struct OptionalExpressionType {};
enum OptionalT {Optional};
template <class Expr>
struct OptionalExpression : public OptionalExpressionType
{
Expr exp;
OptionalExpression(const Expr& e) : exp(e) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "Optional" << std::endl;
result = ResultFalse;
if (begin == end)
return begin;
Iterator it = PatternMatching::Match(begin, end, exp, result);
if (result == ResultFalse)
result = ResultFalseOptional;
else
result = ResultTrueOptional;
return it;
}
};
template<class left, class right>
struct AndExpression
{
left l;
right r;
AndExpression(const left& ll,
const right& rr) : r(rr), l(ll)
{
}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
result = ResultFalse;
if (begin == end)
return begin;
std::cout << "And" << std::endl;
Iterator it = PatternMatching::Match(begin, end, l, result);
if (result == ResultFalse)
return begin;
Iterator it2 = it;
it2++; //passar 1 p frente
it2 = PatternMatching::Match(it2, end, r, result);
if (result == ResultFalse)
return begin;
if (result == ResultFalseOptional)
{
result = ResultTrue;
//fica parado
it = it;
}
else if (result == ResultTrueOptional)
{
result = ResultTrue;
it = it2; //commit
}
else
{
it = it2; //commit
}
return it;
}
};
template<class left, class right>
struct OrExpression
{
left l;
right r;
OrExpression(const left& ll,
const right& rr) : r(rr), l(ll)
{
}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "Or" << std::endl;
Iterator it = PatternMatching::Match(begin, end, l, result);
if (result)
return it;
Iterator it2(it);
it2++;
it2 = PatternMatching::Match(it2, end, r, result);
if (result != ResultFalse)
{
it = it2; //comit
}
return it;
}
};
template<class Iterator>
struct FunctionExpression
{
typedef Iterator(*MatchFunction)(const Iterator& begin,
const Iterator& end,
Result& result);
MatchFunction m_f;
FunctionExpression(MatchFunction f): m_f(f) {}
template<class Iterator>
Iterator Match(const Iterator& begin,
const Iterator& end,
Result& result) const
{
std::cout << "F" << std::endl;
return (*m_f)(begin, end, result);
}
};
template<class Iterator>
FunctionExpression<Iterator> F(Iterator(*f)(const Iterator& begin,
const Iterator& end,
Result& result))
{
return FunctionExpression<Iterator>(f);
}
template<class Expr>
OptionalExpression<Expr> operator *(const Expr& a, OptionalT)
{
return OptionalExpression<Expr>(a);
}
template<class Expr>
OneOrMoreExpression<Expr> operator *(const Expr& a, OneOrMoreT)
{
return OneOrMoreExpression<Expr>(a);
}
template<class Expr>
ZeroOrMoreExpression<Expr> operator *(const Expr& a, ZeroOrMoreT)
{
return ZeroOrMoreExpression<Expr>(a);
}
template<class left, class right>
AndExpression<left, right> operator & (const left& l, const right& r)
{
return AndExpression<left, right>(l, r);
}
template<class left, class right>
OrExpression<left, right> operator | (const left& l, const right& r)
{
return OrExpression<left, right>(l, r);
}
} //namespace PatternMatching
template
std::string::iterator itbegin = in_this_string.begin();
for (; itbegin != in_this_string.end();)
{
Result r;
std::string::iterator it = PatternMatching::Match(itbegin, in_this_string.end(), e, r);
if (r == ResultTrue || r == ResultTrueOptional)
{
size_t pos = itbegin - in_this_string.begin();
in_this_string.replace(itbegin, it + 1, replace);
itbegin = in_this_string.begin() + pos + replace.length();
}
else
{
itbegin++;
}
}
}
template
for (; itbegin != end; itbegin++)
{
PatternMatching::Result r;
Iterator it = PatternMatching::Match(itbegin, end, e, r);
if (r != PatternMatching::ResultFalse)
{
return it;
}
}
}