Pattern matching

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



// 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<class Iterator>
    Iterator Match(const Iterator& begin,
                   const Iterator& end,
                   const typename Iterator::value_type& value,
                   Result& result)
    {
        result = ResultFalse;
        std::cout << "Val" << std::endl;
        if (begin == end)
            return begin;
        result = (*begin == value) ? ResultTrue : ResultFalse;
        if (result)
        {
            return begin;// + 1;
        }
        return begin;
    }


    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<class  Exp>
inline void find_replace(std::string& in_this_string,
                         const Exp& e,
                         const std::string& replace)
{
    using namespace PatternMatching;

    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<class Iterator, class  Exp>
inline Iterator Find(const Iterator& begin,
                     const Iterator& end,
                     const Exp& e)
{
    Iterator itbegin = begin;

    for (; itbegin != end; itbegin++)
    {
        PatternMatching::Result r;
        Iterator it = PatternMatching::Match(itbegin, end, e, r);
        if (r != PatternMatching::ResultFalse)
        {
            return it;
        }
    }
}