Проверено и работает:
— 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");
}