Re: Код: версия 0.00000001
От: TepMuHyc  
Дата: 13.11.03 17:30
Оценка: 15 (1)
Проверено и работает:
— VC 6.0SP5 и старше
— Mingw GCC 3.3.1

#include <stdio.h>
#include <algorithm>

namespace rx_tmpl
{
    namespace impl
    {
        template<wchar_t E, class TAIL>
        struct strn: TAIL
        {
            template<class InIt>
            static bool match(InIt& it, const InIt& end)
            {
                return (it != end) && (E == *it) && TAIL::match(++it,end);
            }
        };

        struct strnlast
        {
            template<class InIt>
            static bool match(InIt& it, const InIt& end)
            {
                return true;
            }
        };

        template<wchar_t E, class TAIL>
        struct setn: TAIL
        {
            static bool do_match(wchar_t ch)
            {
                return (E == ch) || TAIL::do_match(ch);
            }
        };

        struct setnlast
        {
            static bool do_match(wchar_t ch)
            {
                return false;
            }
        };


        template<class RX, class TAIL>
        struct seqn: TAIL
        {
            template<class InIt>
            static bool do_match(InIt& it, const InIt& end)
            {
                return RX::match(it,end) && TAIL::do_match(it,end);
            }
        };

        struct seqnlast
        {
            template<class InIt>
            static bool do_match(InIt& it, const InIt& end)
            {
                return true;
            }
        };
    }//namespace impl

template<wchar_t E>
struct c /* literal charachter */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        bool res = (it != end) && (E == *it);
        if( res ) ++it;
        return res;
    }
};

template<
int c0,     int c1,     int c2 =-1, int c3 =-1, int c4 =-1, int c5 =-1, int c6 =-1, int c7 =-1, int c8 =-1, int c9 =-1,
int c10=-1, int c11=-1, int c12=-1, int c13=-1, int c14=-1, int c15=-1, int c16=-1, int c17=-1, int c18=-1, int c19=-1,
int c20=-1, int c21=-1, int c22=-1, int c23=-1, int c24=-1, int c25=-1, int c26=-1, int c27=-1, int c28=-1, int c29=-1
>
struct s /* literal string - up to 30 symbols */
    :impl::strn<
        c0,
        s<
            c1,c2,c3,c4,c5,c6,c7,c8,c9,
            c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,
            c20,c21,c22,c23,c24,c25,c26,c27,c28,c29,
            -1
        >
    >
{};

template<> 
struct s<
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1>
:impl::strnlast
{};

template<
int c0,     int c1,     int c2 =-1, int c3 =-1, int c4 =-1, int c5 =-1, int c6 =-1, int c7 =-1, int c8 =-1, int c9 =-1,
int c10=-1, int c11=-1, int c12=-1, int c13=-1, int c14=-1, int c15=-1, int c16=-1, int c17=-1, int c18=-1, int c19=-1,
int c20=-1, int c21=-1, int c22=-1, int c23=-1, int c24=-1, int c25=-1, int c26=-1, int c27=-1, int c28=-1, int c29=-1
>
struct set /* charachter set - up to 30 chars - like "[ABCDEFabcdef]"*/
{
    typedef impl::setn<
        c0,
        typename set<
            c1,c2,c3,c4,c5,c6,c7,c8,c9,
            c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,
            c20,c21,c22,c23,c24,c25,c26,c27,c28,c29,
            -1
        >::node
    > node;

    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        bool res = (it != end) && node::do_match(*it);
        if( res ) ++it;
        return res;
    }
};

template<> 
struct set<
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1>
{
    typedef impl::setnlast node;
};

template<wchar_t FRONT, wchar_t BACK, bool INCLUSIVE=true>
struct range /*charachter range - like "[a-d]" or "[^a-d]" */
{
    template<bool> struct sel {};
    //PXT_CASSERT((FRONT < BACK));

    template<class InIt>
    static bool do_match(InIt& it, const InIt& end, sel<true>)
    {
        bool res = (it != end) && (FRONT >= *it) && (*it <= BACK);
        if( res ) ++it;
        return res;
    }

    template<class InIt>
    static bool do_match(InIt& it, const InIt& end, sel<false>)
    {
        return !do_match(it, end, sel<true>());
    }

    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        return do_match(it, end, sel<INCLUSIVE>());
    }
};

struct ws /* whitespace chars */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        bool res = (it != end) && ((*it == ' ') || (*it == '\t'));
        if( res ) ++it;
        return res;
    }
};

struct digit /* numeric chars */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        bool res = (it != end) && (*it >= '0') && (*it <= '9');
        if( res ) ++it;
        return res;
    }
};

struct alpha /* numeric chars */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        bool res = (it != end) && (
            ((*it >= 'A') && (*it <= 'Z')) || 
            ((*it >= 'a') && (*it <= 'z'))
        );
        if( res ) ++it;
        return res;
    }
};

template<class RX>
struct star /*zero or more occurences of RX - like "(abc)*" */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        while( true )
        {
            InIt t(it);
            if( false == RX::match(it, end) || it == t )
                break;
        }
        return true;
    }
};

template<class RX>
struct plus /*one or more occurences of RX - like "(abc)+" */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        return RX::match(it, end) && star<RX>::match(it, end);
    }
};

template<class RX>
struct opt /*optional occurence of RX - like "(abc)?" */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        RX::match(it, end);
        return true;
    }
};

template<class RX1, class RX2>
struct alt /*alternative - like "(abc|def)" */
{
    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        InIt i1(it); bool b1 = RX1::match(i1,end);
        InIt i2(it); bool b2 = RX2::match(i2,end);
        if( b1 && b2 )
            it = (std::max)(i1,i2);
        else if( b1 )
            it = i1;
        else if( b2 )
            it = i2;
        else
            return false;
        return true;
    }
};

struct seqe {};
template<
    class RX0,      class RX1,      class RX2=seqe, class RX3=seqe, class RX4=seqe, 
    class RX5=seqe, class RX6=seqe, class RX7=seqe, class RX8=seqe, class RX9=seqe
>
struct seq 
{
    typedef impl::seqn<
        RX0,
        typename seq<RX1,RX2,RX3,RX4,RX5,RX6,RX7,RX8,RX9,seqe>::node
    > node;

    template<class InIt>
    static bool match(InIt& it, const InIt& end)
    {
        InIt t(it);
        bool res = node::do_match(it,end);
        if( !res ) it = t;
        return res;
    }
};

template<>
struct seq<seqe,seqe,seqe,seqe,seqe,seqe,seqe,seqe,seqe,seqe>
{
    typedef impl::seqnlast node;
};

}//namespace rx_tmpl

namespace myrx
{
    using namespace rx_tmpl;

    typedef 
        seq<
            s<'H','E','L','L','O'>,
            alt< c<','>, ws>,
            star<ws>,
            alt<
                seq<s<'R','E','G','E','X'>, opt< c<'P'> > >,
                seq<s<'R','E','G','U','L','A','R'>, plus<ws>, s<'E','X','P','R','E','S','S','I','O','N'> >
            >
        >
    rx;

    typedef 
        //{D}+(\.{D}+)?([Ee][+-]?{D}+)? 
        seq<
            opt<set<'+','-'> >,
            plus<digit>,
            opt<seq<c<'.'>, plus<digit> > >,
            opt<seq<set<'E','e'>, opt<set<'+','-'> >, plus<digit> > >
        >
    float_num;
}

template<class RX>
void test(char* pp)
{
    char* p = pp;
    bool res = RX::match(p, p+strlen(p));
    printf("\"%s\" %s matched\n", pp, res?"":"not");
}

int main()
{
    test<myrx::float_num>("123");
    test<myrx::float_num>("-123");
    test<myrx::float_num>("123.45");
    test<myrx::float_num>("123E-10");
    test<myrx::float_num>("123.45E-10");
    test<myrx::float_num>("+123.45E-10");
}
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.