mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-11-27 15:30:42 +00:00
- remove unused isInVector
- move AFP stuff into its own namespace - move utf8 and equivset into seperate modules - parser should understand /* */ comments
This commit is contained in:
parent
81343c86c7
commit
ff2465007f
|
@ -6,18 +6,18 @@
|
|||
#include <iostream>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <unicode/utf8.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include "utf8.h"
|
||||
#include "equiv.h"
|
||||
|
||||
#define EQUIVSET_LOC "equivset.txt"
|
||||
namespace afp {
|
||||
|
||||
AFPData
|
||||
af_count(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_count(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to count" );
|
||||
throw exception( "Not enough arguments to count" );
|
||||
}
|
||||
|
||||
string needle, haystack;
|
||||
std::string needle, haystack;
|
||||
|
||||
if (args.size() < 2) {
|
||||
needle = ",";
|
||||
|
@ -40,52 +40,48 @@ af_count(std::vector<AFPData> const &args) {
|
|||
count--;
|
||||
}
|
||||
|
||||
return AFPData((long int)count);
|
||||
return datum((long int)count);
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_norm(vector<AFPData> const &args) {
|
||||
datum
|
||||
af_norm(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to norm" );
|
||||
throw exception( "Not enough arguments to norm" );
|
||||
}
|
||||
|
||||
string orig = args[0].toString();
|
||||
std::string orig = args[0].toString();
|
||||
|
||||
string::const_iterator p, charStart, end;
|
||||
int chr = 0,lastchr = 0;
|
||||
map<int,int> const &equivSet = getEquivSet();
|
||||
string result;
|
||||
std::string::const_iterator p, charStart, end;
|
||||
int chr = 0, lastchr = 0;
|
||||
equiv_set const &equivs = equiv_set::instance();
|
||||
std::string result;
|
||||
|
||||
p = orig.begin();
|
||||
end = orig.end();
|
||||
|
||||
while (chr = next_utf8_char( p, charStart, end )) {
|
||||
std::map<int, int>::const_iterator it;
|
||||
if ((it = equivSet.find(chr)) != equivSet.end()) {
|
||||
chr = it->second;
|
||||
}
|
||||
while (chr = utf8::next_utf8_char( p, charStart, end )) {
|
||||
chr = equivs.get(chr);
|
||||
|
||||
if (chr != lastchr && isalnum(chr)) {
|
||||
result.append(codepointToUtf8(chr));
|
||||
}
|
||||
if (chr != lastchr && isalnum(chr))
|
||||
result.append(utf8::codepoint_to_utf8(chr));
|
||||
|
||||
lastchr = chr;
|
||||
}
|
||||
|
||||
return AFPData(result);
|
||||
return datum(result);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
rmdoubles(std::string const &orig) {
|
||||
string::const_iterator p, charStart, end;
|
||||
std::string::const_iterator p, charStart, end;
|
||||
int chr,lastchr = 0;
|
||||
string result;
|
||||
std::string result;
|
||||
|
||||
p = orig.begin();
|
||||
end = orig.end();
|
||||
while (chr = next_utf8_char( p, charStart, end )) {
|
||||
while (chr = utf8::next_utf8_char( p, charStart, end )) {
|
||||
if (chr != lastchr) {
|
||||
result.append(codepointToUtf8(chr));
|
||||
result.append(utf8::codepoint_to_utf8(chr));
|
||||
}
|
||||
|
||||
lastchr = chr;
|
||||
|
@ -94,277 +90,108 @@ rmdoubles(std::string const &orig) {
|
|||
return result;
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_specialratio(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_specialratio(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to specialratio" );
|
||||
throw exception( "Not enough arguments to specialratio" );
|
||||
}
|
||||
|
||||
string orig = args[0].toString();
|
||||
string::const_iterator p, charStart, end;
|
||||
int chr,lastchr = 0;
|
||||
std::string orig = args[0].toString();
|
||||
std::string::const_iterator p, charStart, end;
|
||||
int chr;
|
||||
int specialcount = 0;
|
||||
|
||||
p = orig.begin();
|
||||
end = orig.end();
|
||||
while (chr = next_utf8_char( p, charStart, end )) {
|
||||
while (chr = utf8::next_utf8_char( p, charStart, end )) {
|
||||
if (!isalnum(chr)) {
|
||||
specialcount++;
|
||||
}
|
||||
}
|
||||
|
||||
double ratio = (float)(specialcount) / (float)(utf8_strlen(orig));
|
||||
double ratio = (float)(specialcount) / (float)(utf8::utf8_strlen(orig));
|
||||
|
||||
return AFPData(ratio);
|
||||
return datum(ratio);
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_rmspecials(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_rmspecials(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to rmspecials" );
|
||||
throw exception( "Not enough arguments to rmspecials" );
|
||||
}
|
||||
|
||||
return AFPData(rmspecials(args[0].toString()));
|
||||
return datum(rmspecials(args[0].toString()));
|
||||
}
|
||||
|
||||
std::string
|
||||
rmspecials(std::string const &orig) {
|
||||
string::const_iterator p, charStart, end;
|
||||
std::string::const_iterator p, charStart, end;
|
||||
int chr = 0;
|
||||
string result;
|
||||
std::string result;
|
||||
|
||||
p = orig.begin();
|
||||
end = orig.end();
|
||||
while (chr = next_utf8_char( p, charStart, end )) {
|
||||
while (chr = utf8::next_utf8_char( p, charStart, end )) {
|
||||
if (isalnum(chr)) {
|
||||
result.append(codepointToUtf8(chr));
|
||||
result.append(utf8::codepoint_to_utf8(chr));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_ccnorm(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_ccnorm(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to ccnorm" );
|
||||
throw exception( "Not enough arguments to ccnorm" );
|
||||
}
|
||||
|
||||
return AFPData( confusable_character_normalise( args[0].toString() ) );
|
||||
return datum( confusable_character_normalise( args[0].toString() ) );
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_rmdoubles(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_rmdoubles(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to rmdoubles" );
|
||||
throw exception( "Not enough arguments to rmdoubles" );
|
||||
}
|
||||
|
||||
return AFPData(rmdoubles(args[0].toString()));
|
||||
return datum(rmdoubles(args[0].toString()));
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_length(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_length(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to lcase" );
|
||||
throw exception( "Not enough arguments to lcase" );
|
||||
}
|
||||
|
||||
return AFPData( (long int)utf8_strlen(args[0].toString()) );
|
||||
return datum( (long int)utf8::utf8_strlen(args[0].toString()) );
|
||||
}
|
||||
|
||||
AFPData
|
||||
af_lcase(std::vector<AFPData> const &args) {
|
||||
datum
|
||||
af_lcase(std::vector<datum> const &args) {
|
||||
if (!args.size()) {
|
||||
throw AFPException( "Not enough arguments to lcase" );
|
||||
throw exception( "Not enough arguments to lcase" );
|
||||
}
|
||||
|
||||
return AFPData(utf8_tolower(args[0].toString()));
|
||||
return datum(utf8::utf8_tolower(args[0].toString()));
|
||||
}
|
||||
|
||||
std::string
|
||||
confusable_character_normalise(std::string const &orig) {
|
||||
string::const_iterator p, charStart, end;
|
||||
std::string::const_iterator p, charStart, end;
|
||||
int chr;
|
||||
map<int,int> const &equivSet = getEquivSet();
|
||||
string result;
|
||||
equiv_set const &equivs = equiv_set::instance();
|
||||
std::string result;
|
||||
|
||||
p = orig.begin();
|
||||
end = orig.end();
|
||||
|
||||
while (chr = next_utf8_char( p, charStart, end )) {
|
||||
map<int, int>::const_iterator it;
|
||||
if ((it = equivSet.find(chr)) != equivSet.end()) {
|
||||
chr = it->second;
|
||||
}
|
||||
|
||||
result.append(codepointToUtf8(chr));
|
||||
while (chr = utf8::next_utf8_char( p, charStart, end )) {
|
||||
chr = equivs.get(chr);
|
||||
result.append(utf8::codepoint_to_utf8(chr));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
map<int,int> const &
|
||||
getEquivSet() {
|
||||
static map<int,int> equivSet;
|
||||
// Map of codepoint:codepoint
|
||||
|
||||
if (equivSet.empty()) {
|
||||
ifstream eqsFile( EQUIVSET_LOC );
|
||||
|
||||
if (!eqsFile) {
|
||||
throw AFPException( "Unable to open equivalence sets!" );
|
||||
}
|
||||
|
||||
string line;
|
||||
|
||||
while (getline(eqsFile,line)) {
|
||||
size_t pos = line.find_first_of( ":", 0 );
|
||||
|
||||
if (pos != line.npos) {
|
||||
// We have a codepoint:codepoint thing.
|
||||
int actual = 0;
|
||||
int canonical = 0;
|
||||
|
||||
istringstream actual_buffer(line.substr(0,pos));
|
||||
istringstream canon_buffer( line.substr(pos+1));
|
||||
actual_buffer >> actual;
|
||||
canon_buffer >> canonical;
|
||||
|
||||
if (actual != 0 && canonical != 0) {
|
||||
equivSet[actual] = canonical;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eqsFile.close();
|
||||
}
|
||||
|
||||
return equivSet;
|
||||
}
|
||||
|
||||
// Weak UTF-8 decoder
|
||||
// Will return garbage on invalid input (overshort sequences, overlong sequences, etc.)
|
||||
// Stolen from wikidiff2 extension by Tim Starling (no point in reinventing the wheel)
|
||||
int
|
||||
next_utf8_char(std::string::const_iterator & p, std::string::const_iterator & charStart,
|
||||
std::string::const_iterator end)
|
||||
{
|
||||
int c=0;
|
||||
unsigned char byte;
|
||||
int bytes = 0;
|
||||
charStart = p;
|
||||
if (p == end) {
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
byte = (unsigned char)*p;
|
||||
if (byte < 0x80) {
|
||||
c = byte;
|
||||
bytes = 0;
|
||||
} else if (byte >= 0xc0) {
|
||||
// Start of UTF-8 character
|
||||
// If this is unexpected, due to an overshort sequence, we ignore the invalid
|
||||
// sequence and resynchronise here
|
||||
if (byte < 0xe0) {
|
||||
bytes = 1;
|
||||
c = byte & 0x1f;
|
||||
} else if (byte < 0xf0) {
|
||||
bytes = 2;
|
||||
c = byte & 0x0f;
|
||||
} else {
|
||||
bytes = 3;
|
||||
c = byte & 7;
|
||||
}
|
||||
} else if (bytes) {
|
||||
c <<= 6;
|
||||
c |= byte & 0x3f;
|
||||
--bytes;
|
||||
} else {
|
||||
// Unexpected continuation, ignore
|
||||
}
|
||||
++p;
|
||||
} while (bytes && p != end);
|
||||
return c;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
utf8_strlen(std::string const &s)
|
||||
{
|
||||
std::size_t ret = 0;
|
||||
for (std::string::const_iterator it = s.begin(), end = s.end();
|
||||
it < end; ++it)
|
||||
{
|
||||
int skip = 1;
|
||||
|
||||
skip = U8_LENGTH(*it);
|
||||
if (it + skip >= end)
|
||||
return ret; /* end of string */
|
||||
|
||||
it += skip;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This could almost certainly be done in a nicer way.
|
||||
*/
|
||||
std::string
|
||||
utf8_tolower(std::string const &s)
|
||||
{
|
||||
std::vector<UChar> ustring;
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
|
||||
for (int i = 0; i < s.size(); ) {
|
||||
UChar32 c;
|
||||
U8_NEXT(s.data(), i, s.size(), c);
|
||||
ustring.push_back(c);
|
||||
}
|
||||
|
||||
std::vector<UChar> dest;
|
||||
u_strToLower(&dest[0], dest.size(), &ustring[0], ustring.size(),
|
||||
NULL, &error);
|
||||
|
||||
if (U_FAILURE(error))
|
||||
return s;
|
||||
|
||||
std::vector<unsigned char> u8string;
|
||||
int i, j;
|
||||
for (i = 0, j = 0; i < dest.size(); j++) {
|
||||
U8_APPEND_UNSAFE(&u8string[0], i, dest[j]);
|
||||
}
|
||||
return std::string(u8string.begin(), u8string.begin() + i);
|
||||
}
|
||||
|
||||
// Ported from MediaWiki core function in PHP.
|
||||
string
|
||||
codepointToUtf8(int codepoint) {
|
||||
string ret;
|
||||
|
||||
if(codepoint < 0x80) {
|
||||
ret.append(1, codepoint);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(codepoint < 0x800) {
|
||||
ret.append(1, codepoint >> 6 & 0x3f | 0xc0);
|
||||
ret.append(1, codepoint & 0x3f | 0x80);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(codepoint < 0x10000) {
|
||||
ret.append(1, codepoint >> 12 & 0x0f | 0xe0);
|
||||
ret.append(1, codepoint >> 6 & 0x3f | 0x80);
|
||||
ret.append(1, codepoint & 0x3f | 0x80);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(codepoint < 0x110000) {
|
||||
ret.append(1, codepoint >> 18 & 0x07 | 0xf0);
|
||||
ret.append(1, codepoint >> 12 & 0x3f | 0x80);
|
||||
ret.append(1, codepoint >> 6 & 0x3f | 0x80);
|
||||
ret.append(1, codepoint & 0x3f | 0x80);
|
||||
return ret;
|
||||
}
|
||||
|
||||
throw AFPException("Asked for code outside of range ($codepoint)\n");
|
||||
}
|
||||
} // namespace afp
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
#ifndef AFFUNCTIONS_H
|
||||
#define AFFUNCTIONS_H
|
||||
|
||||
#include "aftypes.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
AFPData af_length(std::vector<AFPData> const &args);
|
||||
AFPData af_lcase(std::vector<AFPData> const &args);
|
||||
AFPData af_ccnorm(std::vector<AFPData> const &args);
|
||||
AFPData af_rmdoubles(std::vector<AFPData> const &args);
|
||||
AFPData af_specialratio(std::vector<AFPData> const &args);
|
||||
AFPData af_rmspecials(std::vector<AFPData> const &args);
|
||||
AFPData af_norm(std::vector<AFPData> const &args);
|
||||
AFPData af_count(std::vector<AFPData> const &args);
|
||||
#include "aftypes.h"
|
||||
|
||||
map<int,int> const &getEquivSet();
|
||||
int next_utf8_char(std::string::const_iterator & p, std::string::const_iterator & charStart, std::string::const_iterator end);
|
||||
string codepointToUtf8( int codepoint );
|
||||
string confusable_character_normalise(std::string const &orig);
|
||||
vector<AFPData> makeFuncArgList( AFPData arg );
|
||||
AFPData callFunction(string const &name, AFPData arg);
|
||||
string rmdoubles(string const &orig);
|
||||
string rmspecials(string const &orig);
|
||||
std::size_t utf8_strlen(std::string const &s);
|
||||
std::string utf8_tolower(std::string const &s);
|
||||
namespace afp {
|
||||
|
||||
datum af_length (std::vector<datum> const &args);
|
||||
datum af_lcase (std::vector<datum> const &args);
|
||||
datum af_ccnorm (std::vector<datum> const &args);
|
||||
datum af_rmdoubles (std::vector<datum> const &args);
|
||||
datum af_specialratio (std::vector<datum> const &args);
|
||||
datum af_rmspecials (std::vector<datum> const &args);
|
||||
datum af_norm (std::vector<datum> const &args);
|
||||
datum af_count (std::vector<datum> const &args);
|
||||
|
||||
std::string confusable_character_normalise(std::string const &orig);
|
||||
std::string rmdoubles(std::string const &orig);
|
||||
std::string rmspecials(std::string const &orig);
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !AFFUNCTIONS_H */
|
||||
|
|
|
@ -1,30 +1,27 @@
|
|||
#include "aftypes.h"
|
||||
#include <sstream>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
AFPToken::AFPToken(unsigned int new_type, string new_value, unsigned int new_pos) {
|
||||
type = new_type;
|
||||
value = new_value;
|
||||
pos = new_pos;
|
||||
}
|
||||
#include "aftypes.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
AFPData::AFPData(std::string const &var) {
|
||||
datum::datum(std::string const &var) {
|
||||
_init_from_string(var);
|
||||
}
|
||||
|
||||
AFPData::AFPData(char const *var)
|
||||
datum::datum(char const *var)
|
||||
{
|
||||
_init_from_string(var);
|
||||
}
|
||||
|
||||
void
|
||||
AFPData::_init_from_string(std::string const &var)
|
||||
datum::_init_from_string(std::string const &var)
|
||||
{
|
||||
// Try integer
|
||||
try {
|
||||
|
@ -39,35 +36,35 @@ AFPData::_init_from_string(std::string const &var)
|
|||
}
|
||||
}
|
||||
|
||||
AFPData::AFPData() {
|
||||
datum::datum() {
|
||||
}
|
||||
|
||||
AFPData::AFPData(AFPData const &other)
|
||||
datum::datum(datum const &other)
|
||||
: value_(other.value_)
|
||||
{
|
||||
}
|
||||
|
||||
AFPData::AFPData(long int var)
|
||||
datum::datum(long int var)
|
||||
: value_(var)
|
||||
{
|
||||
}
|
||||
|
||||
AFPData::AFPData(double var)
|
||||
datum::datum(double var)
|
||||
: value_(var)
|
||||
{
|
||||
}
|
||||
|
||||
AFPData::AFPData(float var)
|
||||
datum::datum(float var)
|
||||
: value_(var)
|
||||
{
|
||||
}
|
||||
|
||||
AFPData::AFPData(bool var)
|
||||
datum::datum(bool var)
|
||||
: value_((long int) var)
|
||||
{
|
||||
}
|
||||
|
||||
AFPData & AFPData::operator= (AFPData const &other) {
|
||||
datum & datum::operator= (datum const &other) {
|
||||
// Protect against self-assignment
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
|
@ -77,10 +74,6 @@ AFPData & AFPData::operator= (AFPData const &other) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool isInVector(std::string const &needle, std::vector<std::string> const &haystack) {
|
||||
return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a string to an integer value.
|
||||
*/
|
||||
|
@ -108,7 +101,7 @@ struct from_string_converter<std::string> {
|
|||
};
|
||||
|
||||
/*
|
||||
* Conversions from AFPData to other types.
|
||||
* Conversions from datum to other types.
|
||||
*/
|
||||
struct to_string_visitor : boost::static_visitor<std::string> {
|
||||
std::string operator() (std::string const &v) const {
|
||||
|
@ -156,17 +149,17 @@ struct to_double_visitor : boost::static_visitor<double> {
|
|||
};
|
||||
|
||||
std::string
|
||||
AFPData::toString() const {
|
||||
datum::toString() const {
|
||||
return boost::apply_visitor(to_string_visitor(), value_);
|
||||
}
|
||||
|
||||
long int
|
||||
AFPData::toInt() const {
|
||||
datum::toInt() const {
|
||||
return boost::apply_visitor(to_int_visitor(), value_);
|
||||
}
|
||||
|
||||
double
|
||||
AFPData::toFloat() const {
|
||||
datum::toFloat() const {
|
||||
return boost::apply_visitor(to_double_visitor(), value_);
|
||||
}
|
||||
|
||||
|
@ -213,13 +206,13 @@ struct afpmodulus<double> {
|
|||
* after doing appropriate int->double promotion.
|
||||
*/
|
||||
template<template<typename V> class Operator>
|
||||
struct arith_visitor : boost::static_visitor<AFPData> {
|
||||
struct arith_visitor : boost::static_visitor<datum> {
|
||||
/*
|
||||
* Anything involving a double returns a double.
|
||||
* Otherwise, int is returned.
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
AFPData operator() (T const &a, U const &b) const {
|
||||
datum operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<T>::type a_type;
|
||||
typedef typename from_string_converter<U>::type b_type;
|
||||
|
||||
|
@ -272,7 +265,7 @@ struct compare_visitor : boost::static_visitor<bool> {
|
|||
* For comparisons that only work on integers - strings will be converted.
|
||||
*/
|
||||
template<template<typename V> class Operator>
|
||||
struct arith_compare_visitor : boost::static_visitor<AFPData> {
|
||||
struct arith_compare_visitor : boost::static_visitor<datum> {
|
||||
template<typename T, typename U>
|
||||
bool operator() (T const &a, U const &b) const {
|
||||
typedef typename from_string_converter<T>::type a_type;
|
||||
|
@ -285,83 +278,83 @@ struct arith_compare_visitor : boost::static_visitor<AFPData> {
|
|||
}
|
||||
};
|
||||
|
||||
AFPData &
|
||||
AFPData::operator+=(AFPData const &other)
|
||||
datum &
|
||||
datum::operator+=(datum const &other)
|
||||
{
|
||||
AFPData result = boost::apply_visitor(arith_visitor<std::plus>(), value_, other.value_);
|
||||
datum result = boost::apply_visitor(arith_visitor<std::plus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AFPData &
|
||||
AFPData::operator-=(AFPData const &other)
|
||||
datum &
|
||||
datum::operator-=(datum const &other)
|
||||
{
|
||||
AFPData result = boost::apply_visitor(arith_visitor<std::minus>(), value_, other.value_);
|
||||
datum result = boost::apply_visitor(arith_visitor<std::minus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AFPData &
|
||||
AFPData::operator*=(AFPData const &other)
|
||||
datum &
|
||||
datum::operator*=(datum const &other)
|
||||
{
|
||||
AFPData result = boost::apply_visitor(arith_visitor<std::multiplies>(), value_, other.value_);
|
||||
datum result = boost::apply_visitor(arith_visitor<std::multiplies>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AFPData&
|
||||
AFPData::operator/=(AFPData const &other)
|
||||
datum&
|
||||
datum::operator/=(datum const &other)
|
||||
{
|
||||
AFPData result = boost::apply_visitor(arith_visitor<std::divides>(), value_, other.value_);
|
||||
datum result = boost::apply_visitor(arith_visitor<std::divides>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AFPData&
|
||||
AFPData::operator%=(AFPData const &other)
|
||||
datum&
|
||||
datum::operator%=(datum const &other)
|
||||
{
|
||||
AFPData result = boost::apply_visitor(arith_visitor<afpmodulus>(), value_, other.value_);
|
||||
datum result = boost::apply_visitor(arith_visitor<afpmodulus>(), value_, other.value_);
|
||||
*this = result;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AFPData
|
||||
operator+(AFPData const &a, AFPData const &b) {
|
||||
return AFPData(a) += b;
|
||||
datum
|
||||
operator+(datum const &a, datum const &b) {
|
||||
return datum(a) += b;
|
||||
}
|
||||
|
||||
AFPData
|
||||
operator-(AFPData const &a, AFPData const &b) {
|
||||
return AFPData(a) -= b;
|
||||
datum
|
||||
operator-(datum const &a, datum const &b) {
|
||||
return datum(a) -= b;
|
||||
}
|
||||
|
||||
AFPData
|
||||
operator*(AFPData const &a, AFPData const &b) {
|
||||
return AFPData(a) *= b;
|
||||
datum
|
||||
operator*(datum const &a, datum const &b) {
|
||||
return datum(a) *= b;
|
||||
}
|
||||
|
||||
AFPData
|
||||
operator/(AFPData const &a, AFPData const &b) {
|
||||
return AFPData(a) /= b;
|
||||
datum
|
||||
operator/(datum const &a, datum const &b) {
|
||||
return datum(a) /= b;
|
||||
}
|
||||
|
||||
AFPData
|
||||
operator%(AFPData const &a, AFPData const &b) {
|
||||
return AFPData(a) %= b;
|
||||
datum
|
||||
operator%(datum const &a, datum const &b) {
|
||||
return datum(a) %= b;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(AFPData const &a, AFPData const &b) {
|
||||
operator==(datum const &a, datum const &b) {
|
||||
return a.compare(b);
|
||||
}
|
||||
|
||||
bool
|
||||
AFPData::compare(AFPData const &other) const {
|
||||
datum::compare(datum const &other) const {
|
||||
return boost::apply_visitor(compare_visitor<std::equal_to>(), value_, other.value_);
|
||||
}
|
||||
|
||||
bool
|
||||
AFPData::compare_with_type(AFPData const &other) const {
|
||||
datum::compare_with_type(datum const &other) const {
|
||||
if (value_.which() != other.value_.which())
|
||||
return false;
|
||||
|
||||
|
@ -369,36 +362,38 @@ AFPData::compare_with_type(AFPData const &other) const {
|
|||
}
|
||||
|
||||
bool
|
||||
AFPData::less_than(AFPData const &other) const {
|
||||
datum::less_than(datum const &other) const {
|
||||
return boost::apply_visitor(arith_compare_visitor<std::less>(), value_, other.value_);
|
||||
}
|
||||
|
||||
bool
|
||||
operator< (AFPData const &a, AFPData const &b) {
|
||||
operator< (datum const &a, datum const &b) {
|
||||
return a.less_than(b);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<= (AFPData const &a, AFPData const &b) {
|
||||
operator<= (datum const &a, datum const &b) {
|
||||
return a.less_than(b) || a == b;
|
||||
}
|
||||
|
||||
bool
|
||||
operator> (AFPData const &a, AFPData const &b) {
|
||||
operator> (datum const &a, datum const &b) {
|
||||
return !(a <= b);
|
||||
}
|
||||
|
||||
bool
|
||||
operator>= (AFPData const &a, AFPData const &b) {
|
||||
operator>= (datum const &a, datum const &b) {
|
||||
return !(a < b);
|
||||
}
|
||||
|
||||
bool
|
||||
operator!= (AFPData const &a, AFPData const &b) {
|
||||
operator!= (datum const &a, datum const &b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
bool
|
||||
AFPData::operator! () const {
|
||||
datum::operator! () const {
|
||||
return !(int) *this;
|
||||
}
|
||||
|
||||
} // namespace afp
|
||||
|
|
|
@ -8,71 +8,46 @@
|
|||
#include <boost/variant.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using namespace std;
|
||||
namespace afp {
|
||||
|
||||
#define T_NONE 0
|
||||
#define T_ID 1
|
||||
#define T_KEYWORD 2
|
||||
#define T_STRING 3
|
||||
#define T_NUMBER 4
|
||||
#define T_OP 5
|
||||
#define T_BRACE 6
|
||||
#define T_COMMA 7
|
||||
|
||||
#define D_NULL 0
|
||||
#define D_INTEGER 1
|
||||
#define D_FLOAT 2
|
||||
#define D_STRING 3
|
||||
|
||||
#define DATATYPE_MAX 3
|
||||
|
||||
class AFPToken {
|
||||
class datum {
|
||||
public:
|
||||
AFPToken() {}
|
||||
AFPToken(unsigned int type, string value, unsigned int pos);
|
||||
unsigned int type;
|
||||
string value;
|
||||
unsigned int pos;
|
||||
};
|
||||
|
||||
class AFPData {
|
||||
public:
|
||||
AFPData();
|
||||
datum();
|
||||
|
||||
/*
|
||||
* Generic ctor tries to convert to an int.
|
||||
*/
|
||||
template<typename T>
|
||||
AFPData(T const &v)
|
||||
datum(T const &v)
|
||||
: value_(boost::lexical_cast<long int>(v))
|
||||
{
|
||||
}
|
||||
|
||||
// Specific type constructors
|
||||
AFPData( std::string const &var );
|
||||
AFPData( char const *var );
|
||||
AFPData( long int var );
|
||||
AFPData( float var );
|
||||
AFPData( double var );
|
||||
AFPData( bool var );
|
||||
datum( std::string const &var );
|
||||
datum( char const *var );
|
||||
datum( long int var );
|
||||
datum( float var );
|
||||
datum( double var );
|
||||
datum( bool var );
|
||||
|
||||
AFPData( const AFPData & oldData );
|
||||
datum( const datum & oldData );
|
||||
|
||||
// Assignment operator
|
||||
AFPData &operator= (const AFPData & other);
|
||||
datum &operator= (const datum & other);
|
||||
|
||||
AFPData &operator+=(AFPData const &other);
|
||||
AFPData &operator-=(AFPData const &other);
|
||||
AFPData &operator*=(AFPData const &other);
|
||||
AFPData &operator/=(AFPData const &other);
|
||||
AFPData &operator%=(AFPData const &other);
|
||||
datum &operator+=(datum const &other);
|
||||
datum &operator-=(datum const &other);
|
||||
datum &operator*=(datum const &other);
|
||||
datum &operator/=(datum const &other);
|
||||
datum &operator%=(datum const &other);
|
||||
bool operator!() const;
|
||||
|
||||
bool compare(AFPData const &other) const;
|
||||
bool compare_with_type(AFPData const &other) const;
|
||||
bool less_than(AFPData const &other) const;
|
||||
bool compare(datum const &other) const;
|
||||
bool compare_with_type(datum const &other) const;
|
||||
bool less_than(datum const &other) const;
|
||||
|
||||
string toString() const;
|
||||
std::string toString() const;
|
||||
long int toInt() const;
|
||||
double toFloat() const;
|
||||
bool toBool() const {
|
||||
|
@ -108,38 +83,40 @@ protected:
|
|||
valuetype value_;
|
||||
};
|
||||
|
||||
class AFPException :exception {
|
||||
public:
|
||||
const char* what() {return this->s;}
|
||||
AFPException( const char* str ) {s = str;}
|
||||
AFPException( string str, string var ) { char* s1 = new char[1024]; sprintf( s1, str.c_str(), var.c_str() ); s = s1; }
|
||||
AFPException( string str, int var ) { char* s1 = new char[1024]; sprintf( s1, str.c_str(), var ); s = s1; }
|
||||
AFPException( string str, string svar, int ivar ) { char* s1 = new char[1024]; sprintf( s1, str.c_str(), ivar, svar.c_str() ); s = s1; }
|
||||
|
||||
private:
|
||||
const char* s;
|
||||
class exception : std::exception {
|
||||
public:
|
||||
exception(std::string const &what)
|
||||
: what_(what) {}
|
||||
~exception() throw() {}
|
||||
|
||||
char const *what() const throw() {
|
||||
return what_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string what_;
|
||||
};
|
||||
|
||||
AFPData operator+(AFPData const &a, AFPData const &b);
|
||||
AFPData operator-(AFPData const &a, AFPData const &b);
|
||||
AFPData operator*(AFPData const &a, AFPData const &b);
|
||||
AFPData operator/(AFPData const &a, AFPData const &b);
|
||||
AFPData operator%(AFPData const &a, AFPData const &b);
|
||||
datum operator+(datum const &a, datum const &b);
|
||||
datum operator-(datum const &a, datum const &b);
|
||||
datum operator*(datum const &a, datum const &b);
|
||||
datum operator/(datum const &a, datum const &b);
|
||||
datum operator%(datum const &a, datum const &b);
|
||||
|
||||
bool operator==(AFPData const &a, AFPData const &b);
|
||||
bool operator!=(AFPData const &a, AFPData const &b);
|
||||
bool operator<(AFPData const &a, AFPData const &b);
|
||||
bool operator>(AFPData const &a, AFPData const &b);
|
||||
bool operator<=(AFPData const &a, AFPData const &b);
|
||||
bool operator>=(AFPData const &a, AFPData const &b);
|
||||
bool operator==(datum const &a, datum const &b);
|
||||
bool operator!=(datum const &a, datum const &b);
|
||||
bool operator<(datum const &a, datum const &b);
|
||||
bool operator>(datum const &a, datum const &b);
|
||||
bool operator<=(datum const &a, datum const &b);
|
||||
bool operator>=(datum const &a, datum const &b);
|
||||
|
||||
template<typename char_type, typename traits>
|
||||
std::basic_ostream<char_type, traits> &
|
||||
operator<<(std::basic_ostream<char_type, traits> &s, AFPData const &d) {
|
||||
operator<<(std::basic_ostream<char_type, traits> &s, datum const &d) {
|
||||
d.print_to(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
bool isInVector(std::string const &needle, std::vector<std::string> const &haystack);
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !AFTYPES_H */
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
#include "affunctions.h"
|
||||
|
||||
int main( int argc, char** argv ) {
|
||||
filter_evaluator f;
|
||||
afp::filter_evaluator f;
|
||||
|
||||
bool result = false;
|
||||
|
||||
for(int i=0;i<=100;i++) {
|
||||
try {
|
||||
f.add_variable( "foo", AFPData(string("love")) );
|
||||
f.add_variable("foo", afp::datum("love"));
|
||||
result = f.evaluate( "specialratio('foo;') == 0.25" );
|
||||
} catch (AFPException* excep) {
|
||||
} catch (afp::exception* excep) {
|
||||
printf( "Exception: %s\n", excep->what() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include "filter_evaluator.h"
|
||||
#include "request.h"
|
||||
|
||||
int main( int argc, char** argv ) {
|
||||
request r;
|
||||
string result;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
afp::request r;
|
||||
std::string result;
|
||||
|
||||
try {
|
||||
if (!r.load(std::cin))
|
||||
return 1;
|
||||
|
||||
result = r.evaluate();
|
||||
} catch (AFPException excep) {
|
||||
cout << "EXCEPTION: " << excep.what() << endl;
|
||||
cerr << "EXCEPTION: " << excep.what() << endl;
|
||||
} catch (afp::exception &excep) {
|
||||
std::cout << "EXCEPTION: " << excep.what() << std::endl;
|
||||
std::cerr << "EXCEPTION: " << excep.what() << std::endl;
|
||||
}
|
||||
|
||||
cout << result << "\0";
|
||||
std::cout << result << "\0";
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "parser.h"
|
||||
#include "affunctions.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
filter_evaluator::filter_evaluator()
|
||||
{
|
||||
e.add_function("length", af_length);
|
||||
|
@ -26,8 +28,9 @@ filter_evaluator::evaluate(std::string const &filter) const
|
|||
}
|
||||
|
||||
void
|
||||
filter_evaluator::add_variable(std::string const &key, AFPData value)
|
||||
filter_evaluator::add_variable(std::string const &key, datum value)
|
||||
{
|
||||
e.add_variable(key, value);
|
||||
}
|
||||
|
||||
} // namespace afp
|
||||
|
|
|
@ -7,15 +7,19 @@
|
|||
#include "aftypes.h"
|
||||
#include "parser.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
struct filter_evaluator {
|
||||
filter_evaluator();
|
||||
|
||||
bool evaluate(std::string const &filter) const;
|
||||
|
||||
void add_variable(std::string const &key, AFPData value);
|
||||
void add_variable(std::string const &key, datum value);
|
||||
|
||||
private:
|
||||
expressor e;
|
||||
};
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !FILTER_EVALUATOR_H */
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
int main( int argc, char** argv ) {
|
||||
while (true) {
|
||||
request r;
|
||||
afp::request r;
|
||||
bool result = false;
|
||||
|
||||
try {
|
||||
|
@ -35,11 +35,11 @@ int main( int argc, char** argv ) {
|
|||
}
|
||||
|
||||
result = r.evaluate();
|
||||
} catch (AFPException &excep) {
|
||||
cerr << "EXCEPTION: " << excep.what() << endl;
|
||||
} catch (afp::exception &excep) {
|
||||
std::cerr << "EXCEPTION: " << excep.what() << std::endl;
|
||||
}
|
||||
|
||||
cout << ( result ? "MATCH\n" : "NOMATCH\n" );
|
||||
std::cout << ( result ? "MATCH\n" : "NOMATCH\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ af_expr_objs = \
|
|||
af_expr-parser.o \
|
||||
af_expr-filter_evaluator.o \
|
||||
af_expr-eval.o \
|
||||
af_expr-utf8.o \
|
||||
af_expr-equiv.o \
|
||||
af_expr-request.o
|
||||
|
||||
af_parser_objs = \
|
||||
|
@ -21,6 +23,8 @@ af_parser_objs = \
|
|||
af_parser-main.o \
|
||||
af_parser-parser.o \
|
||||
af_parser-request.o \
|
||||
af_parser-utf8.o \
|
||||
af_parser-equiv.o \
|
||||
af_parser-filter_evaluator.o
|
||||
|
||||
check_objs = \
|
||||
|
@ -28,6 +32,8 @@ check_objs = \
|
|||
check-aftypes.o \
|
||||
check-check.o \
|
||||
check-parser.o \
|
||||
check-utf8.o \
|
||||
check-equiv.o \
|
||||
check-filter_evaluator.o
|
||||
|
||||
syntax_check_objs = \
|
||||
|
@ -35,6 +41,8 @@ syntax_check_objs = \
|
|||
syntax_check-aftypes.o \
|
||||
syntax_check-filter_evaluator.o \
|
||||
syntax_check-parser.o \
|
||||
syntax_check-utf8.o \
|
||||
syntax_check-equiv.o \
|
||||
syntax_check-syntax_check.o
|
||||
|
||||
expr_objs = \
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <boost/spirit/phoenix/operators.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include "aftypes.h"
|
||||
#include "parser.h"
|
||||
|
@ -17,30 +18,32 @@ using namespace phoenix;
|
|||
|
||||
namespace px = phoenix;
|
||||
|
||||
namespace afp {
|
||||
|
||||
struct parse_error : std::runtime_error {
|
||||
parse_error(char const *what) : std::runtime_error(what) {}
|
||||
};
|
||||
|
||||
struct parser_closure : boost::spirit::closure<parser_closure, AFPData>
|
||||
struct parser_closure : boost::spirit::closure<parser_closure, datum>
|
||||
{
|
||||
member1 val;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
AFPData f_in(AFPData const &a, AFPData const &b)
|
||||
datum f_in(datum const &a, datum const &b)
|
||||
{
|
||||
std::string sa = a, sb = b;
|
||||
return AFPData(std::search(sb.begin(), sb.end(), sa.begin(), sa.end()) != sb.end());
|
||||
return datum(std::search(sb.begin(), sb.end(), sa.begin(), sa.end()) != sb.end());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct function_closure : boost::spirit::closure<
|
||||
function_closure,
|
||||
AFPData,
|
||||
boost::function<AFPData (std::vector<AFPData>)>,
|
||||
std::vector<AFPData> >
|
||||
datum,
|
||||
boost::function<datum (std::vector<datum>)>,
|
||||
std::vector<datum> >
|
||||
{
|
||||
member1 val;
|
||||
member2 func;
|
||||
|
@ -49,14 +52,14 @@ struct function_closure : boost::spirit::closure<
|
|||
|
||||
struct parser_grammar : public grammar<parser_grammar, parser_closure::context_t>
|
||||
{
|
||||
symbols<AFPData> variables;
|
||||
symbols<boost::function<AFPData (std::vector<AFPData>)> > functions;
|
||||
symbols<datum> variables;
|
||||
symbols<boost::function<datum (std::vector<datum>)> > functions;
|
||||
|
||||
void add_variable(std::string const &name, AFPData const &value) {
|
||||
void add_variable(std::string const &name, datum const &value) {
|
||||
variables.add(name.c_str(), value);
|
||||
}
|
||||
|
||||
void add_function(std::string const &name, boost::function<AFPData (std::vector<AFPData>)> func) {
|
||||
void add_function(std::string const &name, boost::function<datum (std::vector<datum>)> func) {
|
||||
functions.add(name.c_str(), func);
|
||||
}
|
||||
|
||||
|
@ -84,11 +87,11 @@ struct parser_grammar : public grammar<parser_grammar, parser_closure::context_t
|
|||
struct call_function_impl {
|
||||
template<typename F, typename A>
|
||||
struct result {
|
||||
typedef AFPData type;
|
||||
typedef datum type;
|
||||
};
|
||||
|
||||
template<typename F, typename A>
|
||||
AFPData operator() (F const &func, A const &args) const {
|
||||
datum operator() (F const &func, A const &args) const {
|
||||
return func(args);
|
||||
}
|
||||
};
|
||||
|
@ -173,9 +176,9 @@ struct parser_grammar : public grammar<parser_grammar, parser_closure::context_t
|
|||
"==" >> eq_expr[eq2_expr.val = eq2_expr.val == arg1]
|
||||
| "!=" >> eq_expr[eq2_expr.val = eq2_expr.val != arg1]
|
||||
| "===" >> eq_expr[eq2_expr.val =
|
||||
bind(&AFPData::compare_with_type)(eq2_expr.val, arg1)]
|
||||
bind(&datum::compare_with_type)(eq2_expr.val, arg1)]
|
||||
| "!==" >> eq_expr[eq2_expr.val =
|
||||
!bind(&AFPData::compare_with_type)(eq2_expr.val, arg1)]
|
||||
!bind(&datum::compare_with_type)(eq2_expr.val, arg1)]
|
||||
)
|
||||
;
|
||||
|
||||
|
@ -198,7 +201,7 @@ struct parser_grammar : public grammar<parser_grammar, parser_closure::context_t
|
|||
}
|
||||
|
||||
rule_t value, variable, basic, bool_expr,
|
||||
eq_expr, eq2_expr, mult_expr, plus_expr, in_expr, not_expr, expr;
|
||||
eq_expr, eq2_expr, mult_expr, plus_expr, in_expr, expr;
|
||||
rule<ScannerT, function_closure::context_t> function;
|
||||
};
|
||||
};
|
||||
|
@ -213,12 +216,13 @@ expressor::~expressor()
|
|||
delete grammar_;
|
||||
}
|
||||
|
||||
AFPData
|
||||
datum
|
||||
expressor::evaluate(std::string const &filter) const
|
||||
{
|
||||
AFPData ret;
|
||||
datum ret;
|
||||
parse_info<std::string::const_iterator> info =
|
||||
parse(filter.begin(), filter.end(), (*grammar_)[var(ret) = arg1], space_p);
|
||||
parse(filter.begin(), filter.end(), (*grammar_)[var(ret) = arg1],
|
||||
comment_p("/*", "*/") | chset<>("\n\t "));
|
||||
if (info.full) {
|
||||
return ret;
|
||||
} else {
|
||||
|
@ -228,7 +232,7 @@ expressor::evaluate(std::string const &filter) const
|
|||
}
|
||||
|
||||
void
|
||||
expressor::add_variable(std::string const &name, AFPData value)
|
||||
expressor::add_variable(std::string const &name, datum value)
|
||||
{
|
||||
grammar_->add_variable(name, value);
|
||||
}
|
||||
|
@ -239,13 +243,17 @@ expressor::add_function(std::string const &name, func_t value)
|
|||
grammar_->add_function(name, value);
|
||||
}
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#ifdef TEST_PARSER
|
||||
AFPData f_add(std::vector<AFPData> const &args)
|
||||
afp::datum
|
||||
f_add(std::vector<afp::datum> const &args)
|
||||
{
|
||||
return args[0] + args[1];
|
||||
}
|
||||
|
||||
AFPData f_norm(std::vector<AFPData> const &args)
|
||||
afp::datum
|
||||
f_norm(std::vector<afp::datum> const &args)
|
||||
{
|
||||
return args[0];
|
||||
}
|
||||
|
@ -253,7 +261,13 @@ AFPData f_norm(std::vector<AFPData> const &args)
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
expressor e;
|
||||
if (argc != 2) {
|
||||
std::cerr << boost::format("usage: %s <expr>\n")
|
||||
% argv[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
afp::expressor e;
|
||||
e.add_variable("ONE", 1);
|
||||
e.add_variable("TWO", 2);
|
||||
e.add_variable("THREE", 3);
|
||||
|
|
|
@ -9,21 +9,25 @@
|
|||
|
||||
#include "aftypes.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
struct parser_grammar;
|
||||
|
||||
struct expressor : boost::noncopyable {
|
||||
typedef boost::function<AFPData (std::vector<AFPData>)> func_t;
|
||||
typedef boost::function<datum (std::vector<datum>)> func_t;
|
||||
|
||||
expressor();
|
||||
~expressor();
|
||||
|
||||
AFPData evaluate(std::string const &expr) const;
|
||||
datum evaluate(std::string const &expr) const;
|
||||
|
||||
void add_variable(std::string const &name, AFPData value);
|
||||
void add_variable(std::string const &name, datum value);
|
||||
void add_function(std::string const &name, func_t value);
|
||||
|
||||
private:
|
||||
parser_grammar *grammar_;
|
||||
};
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !EXPRESSOR_H */
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#include "request.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
// Protocol:
|
||||
// code NULL <key> NULL <value> NULL ... <value> NULL NULL
|
||||
|
||||
bool
|
||||
request::load(std::istream &inp) {
|
||||
inp.unsetf(ios_base::skipws);
|
||||
inp.unsetf(std::ios_base::skipws);
|
||||
|
||||
std::istream_iterator<char> it(inp), p, end;
|
||||
|
||||
|
@ -55,7 +57,7 @@ request::load(std::istream &inp) {
|
|||
|
||||
it++;
|
||||
|
||||
f.add_variable(key, AFPData(value));
|
||||
f.add_variable(key, datum(value));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -67,3 +69,4 @@ request::evaluate()
|
|||
return f.evaluate(filter);
|
||||
}
|
||||
|
||||
} // namespace afp
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "filter_evaluator.h"
|
||||
|
||||
namespace afp {
|
||||
|
||||
struct request {
|
||||
bool load(std::istream &);
|
||||
bool evaluate(void);
|
||||
|
@ -15,4 +17,6 @@ private:
|
|||
std::string filter;
|
||||
};
|
||||
|
||||
} // namespace afp
|
||||
|
||||
#endif /* !REQUEST_H */
|
||||
|
|
|
@ -5,21 +5,22 @@
|
|||
|
||||
#include "filter_evaluator.h"
|
||||
|
||||
int main( int argc, char** argv ) {
|
||||
stringbuf ss( ios::in | ios::out );
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::stringbuf ss( std::ios::in | std::ios::out );
|
||||
|
||||
// Fill the stringstream
|
||||
cin.get(ss,'\x04');
|
||||
std::cin.get(ss,'\x04');
|
||||
|
||||
string filter = ss.str();
|
||||
std::string filter = ss.str();
|
||||
|
||||
try {
|
||||
filter_evaluator f;
|
||||
afp::filter_evaluator f;
|
||||
f.evaluate(filter);
|
||||
} catch (AFPException excep) {
|
||||
cout << "PARSERR: " << excep.what() << endl;
|
||||
exit(0);
|
||||
} catch (afp::exception &excep) {
|
||||
std::cout << "PARSERR: " << excep.what() << std::endl;
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
cout << "SUCCESS" << endl;
|
||||
std::cout << "SUCCESS" << std::endl;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue