Unicode conversion, phase1: datum should be templated on char type.

added basic_datum<charT>, with typedefs datum and u32datum
This commit is contained in:
River Tarnell 2008-08-09 13:37:58 +00:00
parent dbc2da3177
commit eb5586854e
9 changed files with 696 additions and 493 deletions

26
parser_native/afstring.h Normal file
View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2008 Andrew Garrett.
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
* Derived from public domain code contributed by Victor Vasiliev.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely. This software is provided 'as-is', without any express or
* implied warranty.
*/
#ifndef AFSTRING_H
#define AFSTRING_H
#include <string>
#include <unicode/uchar.h>
typedef std::basic_string<UChar> u32string;
typedef std::basic_istream<UChar> u32istream;
typedef std::basic_ostream<UChar> u32ostream;
typedef std::basic_iostream<UChar> u32iostream;
typedef std::basic_istringstream<UChar> u32istringstream;
typedef std::basic_ostringstream<UChar> u32ostringstream;
typedef std::basic_stringstream<UChar> u32stringstream;
#endif /* !AFSTRING_H */

View file

@ -22,430 +22,6 @@
namespace afp {
datum::datum() {
}
datum::datum(datum const &other)
: value_(other.value_)
{
}
datum
datum::from_string_convert(std::string const &var)
{
// Try integer
try {
return from_int(boost::lexical_cast<long int>(var));
} catch (boost::bad_lexical_cast &e) {
try {
return from_double(boost::lexical_cast<double>(var));
} catch (boost::bad_lexical_cast &e) {
/* If it's nothing else, it's a string */
return from_string(var);
}
}
}
datum
datum::from_string(std::string const &v)
{
datum d;
d.value_ = v;
return d;
}
datum
datum::from_int(long int v)
{
datum d;
d.value_ = v;
return d;
}
datum
datum::from_double(double v)
{
datum d;
d.value_ = v;
return d;
}
template<> datum datum::from<std::string>(std::string const &v) {
return from_string(v);
}
template<> datum datum::from<long int>(long int const &v) {
return from_int(v);
}
template<> datum datum::from<double>(double const &v) {
return from_double(v);
}
datum & datum::operator= (datum const &other) {
// Protect against self-assignment
if (this == &other) {
return *this;
}
value_ = other.value_;
return *this;
}
/*
* Convert a string to an integer value.
*/
template<typename T>
struct from_string_converter {
typedef T type;
static type convert(T const &v) {
return v;
}
};
template<>
struct from_string_converter<std::string> {
typedef long int type;
template<typename T>
static type convert(T const &v) {
try {
return boost::lexical_cast<type>(v);
} catch (boost::bad_lexical_cast &e) {
return 0;
}
}
};
/*
* Conversions from datum to other types.
*/
struct to_string_visitor : boost::static_visitor<std::string> {
std::string operator() (std::string const &v) const {
return v;
}
template<typename T>
std::string operator() (T const &v) const {
return boost::lexical_cast<std::string>(v);
}
};
struct to_int_visitor : boost::static_visitor<long int> {
long int operator() (std::string const &v) const {
try {
return boost::lexical_cast<long int>(v);
} catch (boost::bad_lexical_cast &e) {
return 0;
}
}
long int operator() (double o) const {
return (long int) o;
}
template<typename T>
long int operator() (T const &v) const {
return v;
}
};
struct to_double_visitor : boost::static_visitor<double> {
double operator() (std::string const &v) const {
try {
return boost::lexical_cast<double>(v);
} catch (boost::bad_lexical_cast &e) {
return 0;
}
}
template<typename T>
double operator() (T const &v) const {
return v;
}
};
std::string
datum::toString() const {
return boost::apply_visitor(to_string_visitor(), value_);
}
long int
datum::toInt() const {
return boost::apply_visitor(to_int_visitor(), value_);
}
double
datum::toFloat() const {
return boost::apply_visitor(to_double_visitor(), value_);
}
/* Given T and U, find the preferred type for maths (i.e. double, if present) */
template<typename T, typename U>
struct preferred_type {
typedef T type;
};
template<typename T>
struct preferred_type<double, T> {
typedef double type;
};
template<typename T>
struct preferred_type<T, double> {
typedef double type;
};
template<>
struct preferred_type<double, double> {
typedef double type;
};
/*
* std::modulus doesn't work with double, so we provide our own.
*/
template<typename T>
struct afpmodulus {
T operator() (T const &a, T const &b) const {
return a % b;
}
};
template<>
struct afpmodulus<double> {
double operator() (double const &a, double const &b) const {
return std::fmod(a, b);
}
};
template<typename T>
struct afppower {
T operator() (T const &a, T const &b) const {
return std::pow(a,b);
}
};
/*
* A visitor that performs an arithmetic operation on its arguments,
* after doing appropriate int->double promotion.
*/
template<template<typename V> class Operator>
struct arith_visitor : boost::static_visitor<datum> {
/*
* Anything involving a double returns a double.
* Otherwise, int is returned.
*/
template<typename T, typename U>
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;
Operator<typename preferred_type<a_type, b_type>::type> op;
return datum::from<typename preferred_type<a_type, b_type>::type>(op(
from_string_converter<T>::convert(a),
from_string_converter<U>::convert(b)));
}
/*
* Unary version.
*/
template<typename T>
datum operator() (T const &a) const {
typedef typename from_string_converter<T>::type a_type;
Operator<typename preferred_type<a_type, a_type>::type> op;
return datum::from<typename preferred_type<a_type, a_type>::type>(
op(from_string_converter<T>::convert(a)));
}
};
/*
* Like arith_visitor, but for equality comparisons.
*/
template<
template<typename V> class Operator,
typename T,
typename U>
struct compare_visitor_impl {
bool 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;
Operator<typename preferred_type<a_type, b_type>::type> op;
return op(
from_string_converter<T>::convert(a),
from_string_converter<U>::convert(b));
}
};
/*
* Specialise for string<>string comparisons
*/
template<template<typename V> class Operator>
struct compare_visitor_impl<Operator, std::string, std::string> : boost::static_visitor<bool> {
bool operator() (std::string const &a, std::string const &b) const {
Operator<std::string> op;
return op(a, b);
}
};
template<template<typename V> class Operator>
struct compare_visitor : boost::static_visitor<bool> {
template<typename T, typename U>
bool operator() (T const &a, U const &b) const {
return compare_visitor_impl<Operator, T, U>()(a, b);
}
};
/*
* For comparisons that only work on integers - strings will be converted.
*/
template<template<typename V> class Operator>
struct arith_compare_visitor : boost::static_visitor<bool> {
template<typename T, typename U>
bool 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;
Operator<typename preferred_type<a_type, b_type>::type> op;
return op(
from_string_converter<T>::convert(a),
from_string_converter<U>::convert(b));
}
};
datum &
datum::operator+=(datum const &other)
{
/*
* If either argument is a string, convert both to string. After discussion
* on #mediawiki, this seems to be the least confusing option.
*/
if (value_.which() == 0 || other.value_.which() == 0) {
value_ = toString() + other.toString();
return *this;
}
datum result = boost::apply_visitor(arith_visitor<std::plus>(), value_, other.value_);
*this = result;
return *this;
}
datum &
datum::operator-=(datum const &other)
{
datum result = boost::apply_visitor(arith_visitor<std::minus>(), value_, other.value_);
*this = result;
return *this;
}
datum &
datum::operator*=(datum const &other)
{
datum result = boost::apply_visitor(arith_visitor<std::multiplies>(), value_, other.value_);
*this = result;
return *this;
}
datum&
datum::operator/=(datum const &other)
{
datum result = boost::apply_visitor(arith_visitor<std::divides>(), value_, other.value_);
*this = result;
return *this;
}
datum&
datum::operator%=(datum const &other)
{
datum result = boost::apply_visitor(arith_visitor<afpmodulus>(), value_, other.value_);
*this = result;
return *this;
}
datum
datum::operator+() const
{
return *this;
}
datum
datum::operator-() const
{
return boost::apply_visitor(arith_visitor<std::negate>(), value_);
}
datum
operator+(datum const &a, datum const &b) {
return datum(a) += b;
}
datum
operator-(datum const &a, datum const &b) {
return datum(a) -= b;
}
datum
operator*(datum const &a, datum const &b) {
return datum(a) *= b;
}
datum
operator/(datum const &a, datum const &b) {
return datum(a) /= b;
}
datum
operator%(datum const &a, datum const &b) {
return datum(a) %= b;
}
datum
pow(datum const &a, datum const &b) {
datum result = datum::from_double(std::pow(a.toFloat(),b.toFloat()));
return result;
}
bool
operator==(datum const &a, datum const &b) {
return a.compare(b);
}
bool
datum::compare(datum const &other) const {
return boost::apply_visitor(compare_visitor<std::equal_to>(), value_, other.value_);
}
bool
datum::compare_with_type(datum const &other) const {
if (value_.which() != other.value_.which())
return false;
return boost::apply_visitor(compare_visitor<std::equal_to>(), value_, other.value_);
}
bool
datum::less_than(datum const &other) const {
return boost::apply_visitor(arith_compare_visitor<std::less>(), value_, other.value_);
}
bool
operator< (datum const &a, datum const &b) {
return a.less_than(b);
}
bool
operator<= (datum const &a, datum const &b) {
return a.less_than(b) || a == b;
}
bool
operator> (datum const &a, datum const &b) {
return !(a <= b);
}
bool
operator>= (datum const &a, datum const &b) {

View file

@ -12,12 +12,20 @@
#ifndef AFTYPES_H
#define AFTYPES_H
#include <string>
#include <vector>
#include <iostream>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <ios>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/variant.hpp>
#include <unicode/uchar.h>
namespace afp {
@ -47,58 +55,53 @@ namespace afp {
* entirely stack-based, avoiding memory allocation overhead when manipulating
* datum objects.
*/
class datum {
public:
datum();
datum(datum const &oldData);
template<typename charT>
struct basic_datum {
typedef std::basic_string<charT> string_t;
basic_datum();
basic_datum(basic_datum<charT> const &oldData);
// Type forcing construction functions
static datum from_string(std::string const &v);
static datum from_string_convert(std::string const &v);
static datum from_int(long int v);
static datum from_double(double v);
static basic_datum<charT> from_string(string_t const &v);
static basic_datum<charT> from_string_convert(std::basic_string<charT> const &v);
static basic_datum<charT> from_int(long int v);
static basic_datum<charT> from_double(double v);
/*
* Template versions of the above. See below for the actual
* implementations.
*/
template<typename T> static datum from(T const &v) {
return from_int(0);
}
// Assignment operator
datum &operator= (const datum & other);
basic_datum<charT> &operator= (const basic_datum<charT> & 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);
basic_datum<charT> &operator+=(basic_datum<charT> const &other);
basic_datum<charT> &operator-=(basic_datum<charT> const &other);
basic_datum<charT> &operator*=(basic_datum<charT> const &other);
basic_datum<charT> &operator/=(basic_datum<charT> const &other);
basic_datum<charT> &operator%=(basic_datum<charT> const &other);
bool operator!() const;
datum operator+() const;
datum operator-() const;
basic_datum<charT> operator+() const;
basic_datum<charT> operator-() const;
bool compare(datum const &other) const;
bool compare_with_type(datum const &other) const;
bool less_than(datum const &other) const;
bool compare(basic_datum<charT> const &other) const;
bool compare_with_type(basic_datum<charT> const &other) const;
bool less_than(basic_datum<charT> const &other) const;
std::string toString() const;
string_t toString() const;
long int toInt() const;
double toFloat() const;
bool toBool() const {
return (bool) toInt();
}
template<typename char_type, typename traits>
template<typename traits>
void
print_to(std::basic_ostream<char_type, traits> &s) const {
print_to(std::basic_ostream<charT, traits> &s) const {
s << value_;
}
protected:
void _init_from_string(std::string const &);
void _init_from_string(string_t const &);
typedef boost::variant<std::string, long int, double> valuetype;
typedef boost::variant<string_t, long int, double> valuetype;
valuetype value_;
};
@ -116,33 +119,48 @@ private:
std::string what_;
};
template<> datum datum::from<std::string>(std::string const &v);
template<> datum datum::from<long int>(long int const &v);
template<> datum datum::from<long int>(long int const &v);
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==(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);
datum pow(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, datum const &d) {
d.print_to(s);
return s;
}
#include "datum/create.h"
#include "datum/conversion.h"
#include "datum/operators.h"
namespace afp {
template<typename charT>
basic_datum<charT>::basic_datum() {
}
template<typename charT>
basic_datum<charT>::basic_datum(basic_datum<charT> const &other)
: value_(other.value_)
{
}
template<typename charT>
bool
basic_datum<charT>::compare(basic_datum<charT> const &other) const {
return boost::apply_visitor(datum_impl::compare_visitor<charT, std::equal_to>(), value_, other.value_);
}
template<typename charT>
bool
basic_datum<charT>::compare_with_type(basic_datum<charT> const &other) const {
if (value_.which() != other.value_.which())
return false;
return boost::apply_visitor(datum_impl::compare_visitor<charT, std::equal_to>(), value_, other.value_);
}
template<typename charT>
bool
basic_datum<charT>::less_than(basic_datum<charT> const &other) const {
return boost::apply_visitor(datum_impl::arith_compare_visitor<charT, std::less>(), value_, other.value_);
}
typedef basic_datum<char> datum;
typedef basic_datum<UChar> u32datum;
} // namespace afp
#endif /* !AFTYPES_H */

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2008 Andrew Garrett.
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
* Derived from public domain code contributed by Victor Vasiliev.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely. This software is provided 'as-is', without any express or
* implied warranty.
*/
#ifndef DATUM_CONVERSION_H
#define DATUM_CONVERSION_H
#include "datum/visitors.h"
namespace afp {
template<typename charT>
basic_datum<charT>
basic_datum<charT>::from_string_convert(basic_datum<charT>::string_t const &var)
{
// Try integer
try {
return from_int(boost::lexical_cast<long int>(var));
} catch (boost::bad_lexical_cast &e) {
try {
return from_double(boost::lexical_cast<double>(var));
} catch (boost::bad_lexical_cast &e) {
/* If it's nothing else, it's a string */
return from_string(var);
}
}
}
template<typename charT>
basic_datum<charT>
basic_datum<charT>::from_string(basic_datum<charT>::string_t const &v)
{
basic_datum<charT> d;
d.value_ = v;
return d;
}
template<typename charT>
basic_datum<charT>
basic_datum<charT>::from_int(long int v)
{
basic_datum<charT> d;
d.value_ = v;
return d;
}
template<typename charT>
basic_datum<charT>
basic_datum<charT>::from_double(double v)
{
basic_datum<charT> d;
d.value_ = v;
return d;
}
template<typename charT>
std::basic_string<charT>
basic_datum<charT>::toString() const {
return boost::apply_visitor(datum_impl::to_string_visitor<charT>(), value_);
}
template<typename charT>
long int
basic_datum<charT>::toInt() const {
return boost::apply_visitor(datum_impl::to_int_visitor<charT>(), value_);
}
template<typename charT>
double
basic_datum<charT>::toFloat() const {
return boost::apply_visitor(datum_impl::to_double_visitor<charT>(), value_);
}
} // namespace afp
#endif /* !DATUM_CONVERSION_H */

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2008 Andrew Garrett.
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
* Derived from public domain code contributed by Victor Vasiliev.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely. This software is provided 'as-is', without any express or
* implied warranty.
*/
#ifndef DATUM_CREATE_H
#define DATUM_CREATE_H
namespace afp {
template<typename charT, typename T>
struct create_datum;
template<typename charT>
struct create_datum<charT, long int> {
static basic_datum<charT> create(long int v) {
return basic_datum<charT>::from_int(v);
}
};
template<typename charT>
struct create_datum<charT, double> {
static basic_datum<charT> create(double v) {
return basic_datum<charT>::from_double(v);
}
};
template<typename charT>
struct create_datum<charT, std::string> {
static basic_datum<charT> create(std::basic_string<charT> const &v) {
return basic_datum<charT>::from_string(v);
}
};
}
#endif /* !DATUM_CREATE_H */

View file

@ -0,0 +1,239 @@
/*
* Copyright (c) 2008 Andrew Garrett.
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
* Derived from public domain code contributed by Victor Vasiliev.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely. This software is provided 'as-is', without any express or
* implied warranty.
*/
#ifndef DATUM_OPERATORS_H
#define DATUM_OPERATORS_H
#include "datum/visitors.h"
namespace afp {
namespace datum_impl {
/*
* std::modulus doesn't work with double, so we provide our own.
*/
template<typename T>
struct afpmodulus {
T operator() (T const &a, T const &b) const {
return a % b;
}
};
template<>
struct afpmodulus<double> {
double operator() (double const &a, double const &b) const {
return std::fmod(a, b);
}
};
template<typename T>
struct afppower {
T operator() (T const &a, T const &b) const {
return std::pow(a,b);
}
};
} // namespace datum_impl
template<typename charT>
basic_datum<charT> operator+(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
basic_datum<charT> operator-(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
basic_datum<charT> operator*(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
basic_datum<charT> operator/(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
basic_datum<charT> operator%(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
bool operator==(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
bool operator!=(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
bool operator<(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
bool operator>(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
bool operator<=(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
bool operator>=(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT>
basic_datum<charT> pow(basic_datum<charT> const &a, basic_datum<charT> const &b);
template<typename charT, typename char_type, typename traits>
std::basic_ostream<char_type, traits> &
operator<<(std::basic_ostream<char_type, traits> &s, basic_datum<charT> const &d) {
d.print_to(s);
return s;
}
template<typename charT>
basic_datum<charT> &
basic_datum<charT>::operator= (basic_datum<charT> const &other) {
value_ = other.value_;
return *this;
}
template<typename charT>
basic_datum<charT> &
basic_datum<charT>::operator+=(basic_datum<charT> const &other)
{
/*
* If either argument is a string, convert both to string. After discussion
* on #mediawiki, this seems to be the least confusing option.
*/
if (value_.which() == 0 || other.value_.which() == 0) {
value_ = toString() + other.toString();
return *this;
}
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::plus>(), value_, other.value_);
*this = result;
return *this;
}
template<typename charT>
basic_datum<charT> &
basic_datum<charT>::operator-=(basic_datum<charT> const &other)
{
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::minus>(), value_, other.value_);
*this = result;
return *this;
}
template<typename charT>
basic_datum<charT> &
basic_datum<charT>::operator*=(basic_datum<charT> const &other)
{
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::multiplies>(), value_, other.value_);
*this = result;
return *this;
}
template<typename charT>
basic_datum<charT>&
basic_datum<charT>::operator/=(basic_datum<charT> const &other)
{
basic_datum<charT> result = boost::apply_visitor(datum_impl::arith_visitor<charT, std::divides>(), value_, other.value_);
*this = result;
return *this;
}
template<typename charT>
basic_datum<charT>&
basic_datum<charT>::operator%=(basic_datum<charT> const &other)
{
basic_datum<charT> result = boost::apply_visitor(
datum_impl::arith_visitor<charT, datum_impl::afpmodulus>(), value_, other.value_);
*this = result;
return *this;
}
template<typename charT>
basic_datum<charT>
basic_datum<charT>::operator+() const
{
return *this;
}
template<typename charT>
basic_datum<charT>
basic_datum<charT>::operator-() const
{
return boost::apply_visitor(datum_impl::arith_visitor<charT, std::negate>(), value_);
}
template<typename charT>
basic_datum<charT>
operator+(basic_datum<charT> const &a, basic_datum<charT> const &b) {
return basic_datum<charT>(a) += b;
}
template<typename charT>
basic_datum<charT>
operator-(basic_datum<charT> const &a, basic_datum<charT> const &b) {
return basic_datum<charT>(a) -= b;
}
template<typename charT>
basic_datum<charT>
operator*(basic_datum<charT> const &a, basic_datum<charT> const &b) {
return basic_datum<charT>(a) *= b;
}
template<typename charT>
basic_datum<charT>
operator/(basic_datum<charT> const &a, basic_datum<charT> const &b) {
return basic_datum<charT>(a) /= b;
}
template<typename charT>
basic_datum<charT>
operator%(basic_datum<charT> const &a, basic_datum<charT> const &b) {
return basic_datum<charT>(a) %= b;
}
template<typename charT>
basic_datum<charT>
pow(basic_datum<charT> const &a, basic_datum<charT> const &b) {
basic_datum<charT> result = basic_datum<charT>::from_double(std::pow(a.toFloat(),b.toFloat()));
return result;
}
template<typename charT>
bool
operator==(basic_datum<charT> const &a, basic_datum<charT> const &b) {
return a.compare(b);
}
template<typename charT>
bool
operator< (basic_datum<charT> const &a, basic_datum<charT> const &b) {
return a.less_than(b);
}
template<typename charT>
bool
operator<= (basic_datum<charT> const &a, basic_datum<charT> const &b) {
return a.less_than(b) || a == b;
}
template<typename charT>
bool
operator> (basic_datum<charT> const &a, basic_datum<charT> const &b) {
return !(a <= b);
}
template<typename charT>
bool
operator>= (basic_datum<charT> const &a, basic_datum<charT> const &b) {
return !(a < b);
}
template<typename charT>
bool
operator!= (basic_datum<charT> const &a, basic_datum<charT> const &b) {
return !(a == b);
}
template<typename charT>
bool
basic_datum<charT>::operator! () const {
return !toBool();
}
} // namespace afp
#endif /* !DATUM_OPERATORS_H */

View file

@ -0,0 +1,223 @@
/*
* Copyright (c) 2008 Andrew Garrett.
* Copyright (c) 2008 River Tarnell <river@wikimedia.org>
* Derived from public domain code contributed by Victor Vasiliev.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely. This software is provided 'as-is', without any express or
* implied warranty.
*/
#ifndef DATUM_VISITORS_H
#define DATUM_VISITORS_H
#include "datum/create.h"
namespace afp {
namespace datum_impl {
/* Given T and U, find the preferred type for maths (i.e. double, if present) */
template<typename T, typename U>
struct preferred_type {
typedef T type;
};
template<typename T>
struct preferred_type<double, T> {
typedef double type;
};
template<typename T>
struct preferred_type<T, double> {
typedef double type;
};
template<>
struct preferred_type<double, double> {
typedef double type;
};
/*
* Convert a string to an integer value.
*/
template<typename charT, typename T>
struct from_string_converter {
typedef T type;
static type convert(T const &v) {
return v;
}
};
template<typename charT>
struct from_string_converter<charT, std::basic_string<charT> > {
typedef long int type;
template<typename T>
static type convert(T const &v) {
try {
return boost::lexical_cast<type>(v);
} catch (boost::bad_lexical_cast &e) {
return 0;
}
}
};
/*
* Conversions from datum to other types.
*/
template<typename charT>
struct to_string_visitor : boost::static_visitor<std::basic_string<charT> > {
std::basic_string<charT> operator() (std::basic_string<charT> const &v) const {
return v;
}
template<typename T>
std::basic_string<charT> operator() (T const &v) const {
return boost::lexical_cast<std::basic_string<charT> >(v);
}
};
template<typename charT>
struct to_int_visitor : boost::static_visitor<long int> {
long int operator() (std::basic_string<charT> const &v) const {
try {
return boost::lexical_cast<long int>(v);
} catch (boost::bad_lexical_cast &e) {
return 0;
}
}
long int operator() (double o) const {
return (long int) o;
}
template<typename T>
long int operator() (T const &v) const {
return v;
}
};
template<typename charT>
struct to_double_visitor : boost::static_visitor<double> {
double operator() (std::basic_string<charT> const &v) const {
try {
return boost::lexical_cast<double>(v);
} catch (boost::bad_lexical_cast &e) {
return 0;
}
}
template<typename T>
double operator() (T const &v) const {
return v;
}
};
/*
* A visitor that performs an arithmetic operation on its arguments,
* after doing appropriate int->double promotion.
*/
template<typename charT, template<typename V> class Operator>
struct arith_visitor : boost::static_visitor<basic_datum<charT> > {
/*
* Anything involving a double returns a double.
* Otherwise, int is returned.
*/
template<typename T, typename U>
basic_datum<charT> operator() (T const &a, U const &b) const {
typedef typename from_string_converter<charT, T>::type a_type;
typedef typename from_string_converter<charT, U>::type b_type;
typedef typename preferred_type<a_type, b_type>::type preferred_type;
Operator<preferred_type> op;
return create_datum<charT, preferred_type>::create(op(
from_string_converter<charT, T>::convert(a),
from_string_converter<charT, U>::convert(b)));
}
/*
* Unary version.
*/
template<typename T>
basic_datum<charT> operator() (T const &a) const {
typedef typename from_string_converter<charT, T>::type a_type;
typedef typename preferred_type<a_type, a_type>::type preferred_type;
Operator<preferred_type> op;
return create_datum<charT, preferred_type>::create(
op(from_string_converter<charT, T>::convert(a)));
}
};
/*
* Like arith_visitor, but for equality comparisons.
*/
template<
typename charT,
template<typename V> class Operator,
typename T,
typename U>
struct compare_visitor_impl {
bool operator() (T const &a, U const &b) const {
typedef typename from_string_converter<charT, T>::type a_type;
typedef typename from_string_converter<charT, U>::type b_type;
typedef typename preferred_type<a_type, b_type>::type preferred_type;
Operator<preferred_type> op;
return op(
from_string_converter<charT, T>::convert(a),
from_string_converter<charT, U>::convert(b));
}
};
/*
* Specialise for string<>string comparisons
*/
template<typename charT, template<typename V> class Operator>
struct compare_visitor_impl<
charT,
Operator,
std::basic_string<charT>,
std::basic_string<charT>
> : boost::static_visitor<bool> {
bool operator() (std::basic_string<charT> const &a, std::basic_string<charT> const &b) const {
Operator<std::basic_string<charT> > op;
return op(a, b);
}
};
template<typename charT, template<typename V> class Operator>
struct compare_visitor : boost::static_visitor<bool> {
template<typename T, typename U>
bool operator() (T const &a, U const &b) const {
return compare_visitor_impl<charT, Operator, T, U>()(a, b);
}
};
/*
* For comparisons that only work on integers - strings will be converted.
*/
template<typename charT, template<typename V> class Operator>
struct arith_compare_visitor : boost::static_visitor<bool> {
template<typename T, typename U>
bool operator() (T const &a, U const &b) const {
typedef typename from_string_converter<charT, T>::type a_type;
typedef typename from_string_converter<charT, U>::type b_type;
typedef typename preferred_type<a_type, b_type>::type preferred_type;
Operator<preferred_type> op;
return op(
from_string_converter<charT, T>::convert(a),
from_string_converter<charT, U>::convert(b));
}
};
} // namespace datum_impl
} // namespace afp
#endif /* !DATUM_VISITORS_H */

View file

@ -9,7 +9,7 @@
include makefile.config
CPPFLAGS = $(EXTRA_CPPFLAGS)
CPPFLAGS = -Iinclude $(EXTRA_CPPFLAGS)
LDFLAGS = $(EXTRA_LDFLAGS)
LIBS = -lboost_regex$(BOOST_TAG) -licuuc -licui18n -licudata
@ -18,7 +18,6 @@ expr: CPPFLAGS+=-DTEST_PARSER
af_expr_objs = \
af_expr-affunctions.o \
af_expr-aftypes.o \
af_expr-parser.o \
af_expr-filter_evaluator.o \
af_expr-eval.o \
@ -28,7 +27,6 @@ af_expr_objs = \
af_parser_objs = \
af_parser-affunctions.o \
af_parser-aftypes.o \
af_parser-main.o \
af_parser-parser.o \
af_parser-request.o \
@ -38,7 +36,6 @@ af_parser_objs = \
check_objs = \
check-affunctions.o \
check-aftypes.o \
check-check.o \
check-parser.o \
check-utf8.o \
@ -47,7 +44,6 @@ check_objs = \
syntax_check_objs = \
syntax_check-affunctions.o \
syntax_check-aftypes.o \
syntax_check-filter_evaluator.o \
syntax_check-parser.o \
syntax_check-utf8.o \
@ -55,7 +51,6 @@ syntax_check_objs = \
syntax_check-syntax_check.o
expr_objs = \
expr-aftypes.o \
expr-parser.o
progs = check af_parser syntax_check af_expr expr

View file

@ -370,7 +370,7 @@ struct parser_grammar : public grammar<parser_grammar, parser_closure::context_t
pow_expr =
in_expr[pow_expr.val = arg1]
>> !(
"**" >> pow_expr[pow_expr.val = bind(&afp::pow)(pow_expr.val, arg1)]
"**" >> pow_expr[pow_expr.val = bind(&afp::pow<char>)(pow_expr.val, arg1)]
)
;