An error occurred while loading the file. Please try again.
-
ilor authored85ec635b
parsedexpression.h 8.85 KiB
#ifndef LIBWCCL_OPS_PARSEDEXPRESSION_H
#define LIBWCCL_OPS_PARSEDEXPRESSION_H
#include <libwccl/ops/expression.h>
#include <libwccl/variables.h>
namespace Wccl {
/**
* Abstract base class for WCCL expressions coming from parser and thus
* having a set of variables.
* @attention Usage of the class is not thread safe, but you can
* create a copy and the copy can run concurrently, beacuse it has its
* own set of variables.
* @note See below for various usage of the class.
* \code
* // op is a ParsedExpression and op_ptr a (shared) pointer to it.
* std::string s;
* s = op["Foo"].to_raw_string();
* s = (*op_ptr)["Foo"].to_raw_string();
* // versus
* s = op.get<Wccl::Bool>("Foo").to_raw_string();
* s = op_ptr->get<Wccl::Bool>("Foo").to_raw_string();
* // but!
* Wccl::Bool b;
* op["Foo"] = b; // NOT OK! compile error!
* op.get<Wccl::Bool>("Foo") = b; // OK
* op.set("Foo", b); // alternative for setting the value
* \endcode
*/
class ParsedExpression : public Expression
{
public:
/**
* operator[] that gets value of a variable with given name.
* @param var_name Variable name.
* @returns Const reference to value of the variable.
* @throws InvalidVariableName if the expression doesn't have variable
* of given name.
* @note This allows only read-only (const) access to value, using the base
* type Value. There would be no way to guarantee proper type if assignment
* to returned reference had been allowed.
* @see \link get(const std::string& var_name) const get<T> const \endlink -
* a version that returns concrete type of Value.
* @see \link get(const std::string& var_name) get<T> \endlink - a version
* that returns concrete type of Value and also allows assignment of the value.
* @see set<T> - a convenience function if all you want is to assign
* value to a variable.
*/
const Value& operator[](const std::string& var_name) const;
/**
* Gets value of a variable with given name and type.
* @returns Const reference to value of the variable of type T.
* @param var_name Variable name.
* @throws InvalidVariableName if the expression doesn't have variable
* of given name.
* @throws VariableTypeMismatch if the expression has variable of the given
* name, but its type is different than the supplied T.
* @see \link operator[]() operator[] \endlink - a version that returns
* the value using base type Value, which may be more convenient
* in some situations.
* @see \link get(const std::string& var_name) get<T> \endlink - non-const
* version that allows assignment of a value to the result
* @see set<T> - a convenience function if all you want is to assign
* value to a variable.
*/
template<class T>
const T& get(const std::string& var_name) const;
/**
* Gets value of a variable with given name and type, allowing for
* assignment.
* @returns Reference to Value of the variable of type T. You can assign
* values to the result and that changes value of the variable accordingly.
* @param var_name Variable name.
* @throws InvalidVariableName if the expression doesn't have variable
* of given name.
* @throws VariableTypeMismatch if the expression has variable of the given
* name, but its type is different than the supplied T.
* @see \link operator[]() operator[] \endlink - a version that returns
* the value using base type Value, which may be more convenient
* in some situations (but doesn't allow assignment to the result)
* @see \link get(const std::string& var_name) const get<T> const \endlink -
* the const version (which doesn't allow assignment to the result)
* @see set<T> - a convenience function if all you want is to assign
* a value to a variable.
*/
template<class T>
T& get(const std::string& var_name);
/**
* Assigns value to a variable with given name and type.
* @param var_name Variable name.
* @param value Value to assign.
* @throws InvalidVariableName if the expression doesn't have variable
* of given name.
* @throws VariableTypeMismatch if the expression has variable of the given
* name, but its type is different than the supplied T.
* @note This may be more convenient than assiging a value via get, because
* the type T is inferred from the parameter value:
* \code
* Bool b;
* op.set("Foo", b) //notice that set<Bool> isn't required
* //versus
* op.get<Bool>("Foo") = b; // specification of type is required
* \endcode
* @see get<T> - allows assignment of the value with assignment operator,
* but requires explicit specification of T.
*/
template<class T>
void set(const std::string& var_name, const T& value);
/**
* Sets all variables to their default values.
* @note Values of variables are preserved between applications
* of the expression. If the expression depends on some variables
* that it isn't setting by itself prior to the usage, you probably
* want to reset those variables yourself before each run, or you may
* call clean() depending on the situation.
* Also, derived classes that have clone() method copy the values
* as well, but a class may provide convenience method clone_clean()
* in case you want to get a clean state.
*/
void clean();
/**
* @returns A copy of the expression, with values of the variables
* copied as well.
* @see clone_clean_ptr - convenience version that returns clean copy.
*/
boost::shared_ptr<ParsedExpression> clone_ptr() const;
/**
* @returns A copy of the expression, with values of the variables
* set to their defaults.
* @see clone_ptr - a version that keeps values of the variables.
*/
boost::shared_ptr<ParsedExpression> clone_clean_ptr() const;
/**
* @returns vector of strings corresponfing to valid variable names
* in this operator.
*/
std::vector<std::string> valid_variable_names() const;
/**
* @returns String with representation of all held variables,
* in form of "variable = value" pairs, each pair on one line.
*/
std::string variables_string(const Corpus2::Tagset& tagset) const;
/**
* Dump all variables to an output stream, in form of
* "variable = value" pairs, each pair on another line.
* @returns Stream written to.
*/
std::ostream& dump_variables(std::ostream& ostream, const Corpus2::Tagset& tagset) const;
protected:
explicit ParsedExpression(const Variables& variables);
boost::shared_ptr<Variables> variables_;
virtual ParsedExpression* clone_internal() const = 0;
};
//--- implementation details ---
inline
ParsedExpression::ParsedExpression(const Variables &variables)
: variables_(variables.clone())
{
}
inline
const Value& ParsedExpression::operator[](const std::string& var_name) const {
boost::shared_ptr<Value> value = variables_->get<Value>(var_name);
if (!value) {
throw InvalidVariableName(var_name);
}
return *value;
}
template <class T> inline
const T& ParsedExpression::get(const std::string &var_name) const {
BOOST_MPL_ASSERT_NOT(( boost::is_same<T, Value> ));
boost::shared_ptr<T> value = variables_->get<T>(var_name);
if (!value) {
if (!variables_->get<Value>(var_name)) {
throw InvalidVariableName(var_name);
} else {
throw VariableTypeMismatch(var_name);
}
}
return *value;
}
template <class T> inline
T& ParsedExpression::get(const std::string &var_name) {
BOOST_MPL_ASSERT_NOT(( boost::is_same<T, Value> ));
boost::shared_ptr<T> value = variables_->get<T>(var_name);
if (!value) {
if (!variables_->get<Value>(var_name)) {
throw InvalidVariableName(var_name);
} else {
throw VariableTypeMismatch(var_name);
}
}
return *value;
}
template<class T> inline
void ParsedExpression::set(const std::string& var_name, const T& value) {
get<T>(var_name) = value;
}
inline
void ParsedExpression::clean()
{
variables_->reset_values();
}
inline
boost::shared_ptr<ParsedExpression> ParsedExpression::clone_ptr() const {
return boost::shared_ptr<ParsedExpression>(clone_internal());
}
inline
boost::shared_ptr<ParsedExpression> ParsedExpression::clone_clean_ptr() const {
boost::shared_ptr<ParsedExpression> copy(clone_internal());
BOOST_ASSERT(copy);
copy->clean();
return copy;
}
inline
std::vector<std::string> ParsedExpression::valid_variable_names() const {
std::vector<std::string> valid;
typedef std::pair<std::string, boost::shared_ptr<Wccl::Value> > v_t;
// ja chcę c++1x i auto/decltype
foreach (const v_t& v, variables_->get_all<Wccl::Value>()) {
valid.push_back(v.first);
}
return valid;
}
inline
std::ostream& ParsedExpression::dump_variables(
std::ostream &ostream,
const Corpus2::Tagset &tagset) const {
typedef std::pair<std::string, boost::shared_ptr<Wccl::Value> > v_t;
foreach (const v_t& v, variables_->get_all<Wccl::Value>()) {
ostream << v.second->make_var_repr(v.first) << "="
<< v.second->to_string(tagset) << "\n";
}
return ostream;
}
inline
std::string ParsedExpression::variables_string(const Corpus2::Tagset &tagset) const {
std::ostringstream oss;
dump_variables(oss, tagset);
return oss.str();
}
} /* end ns Wccl */
#endif // LIBWCCL_OPS_PARSEDEXPRESSION_H