Changed to allow simpler notation in actions.

This commit is contained in:
yhirose 2015-02-11 20:31:11 -05:00
parent 8acb0e2822
commit 4202e6d111
3 changed files with 28 additions and 13 deletions

View File

@ -97,7 +97,7 @@ assert(val == -3);
It may be helpful to keep in mind that the action behavior is similar to the YACC semantic action model ($$, $1, $2, ...). It may be helpful to keep in mind that the action behavior is similar to the YACC semantic action model ($$, $1, $2, ...).
In this example, the actions return values. These samentic values will be pushed up to the parent definition which can be referred to in the parent action `[](const vector<Any>& v)`. In other words, when a certain definition has been accepted, we can find all semantic values which are associated with the child definitions in `const vector<Any>& v`. The values are wrapped by peblib::Any class which is like `boost::any`. We can retrieve the value by using `get<T>` method where `T` is the actual type of the value. If no value is returned in an action, an undefined `Any` will be pushed up to the parent. Finally, the resulting value of the root definition is received in the out parameter of `parse` method in the parser. `long val` is the resulting value in this case. In this example, the actions return values. These samentic values will be pushed up to the parent definition which can be referred to in the parent action `[](const vector<Any>& v)`. In other words, when a certain definition has been accepted, we can find all semantic values which are associated with the child definitions in `const vector<Any>& v`. The values are wrapped by peglib::Any class which is like `boost::any`. We can retrieve the value by using `get<T>` method where `T` is the actual type of the value. If no value is returned in an action, an undefined `Any` will be pushed up to the parent. Finally, the resulting value of the root definition is received in the out parameter of `parse` method in the parser. `long val` is the resulting value in this case.
Here are available user actions: Here are available user actions:

View File

@ -115,15 +115,24 @@ public:
return *this; return *this;
} }
operator const std::string&() const {
return get<std::string>();
}
operator std::string&() {
return get<std::string>();
}
// TODO: Add more implecit cast operators // TODO: Add more implecit cast operators
operator bool() const { return get<bool>(); }
operator char() const { return get<char>(); }
operator wchar_t() const { return get<wchar_t>(); }
operator char16_t() const { return get<char16_t>(); }
operator char32_t() const { return get<char32_t>(); }
operator unsigned char() const { return get<unsigned char>(); }
operator int() const { return get<int>(); }
operator unsigned int() const { return get<unsigned int>(); }
operator short() const { return get<short>(); }
operator unsigned short() const { return get<unsigned short>(); }
operator long() const { return get<long>(); }
operator unsigned long() const { return get<unsigned long>(); }
operator long long() const { return get<long long>(); }
operator unsigned long long() const { return get<unsigned long long>(); }
operator float() const { return get<float>(); }
operator double() const { return get<double>(); }
operator const std::string&() const { return get<std::string>(); }
private: private:
struct placeholder { struct placeholder {
@ -189,13 +198,16 @@ public:
//Action(Action&& rhs) : fn_(std::move(rhs.fn_)) {} //Action(Action&& rhs) : fn_(std::move(rhs.fn_)) {}
template <typename F, typename std::enable_if<!std::is_pointer<F>::value>::type*& = enabler> template <typename F, typename std::enable_if<!std::is_pointer<F>::value && !std::is_null_pointer<F>::value>::type*& = enabler>
Action(F fn) : fn_(make_adaptor(fn, &F::operator())) {} Action(F fn) : fn_(make_adaptor(fn, &F::operator())) {}
template <typename F, typename std::enable_if<std::is_pointer<F>::value>::type*& = enabler> template <typename F, typename std::enable_if<std::is_pointer<F>::value>::type*& = enabler>
Action(F fn) : fn_(make_adaptor(fn, fn)) {} Action(F fn) : fn_(make_adaptor(fn, fn)) {}
template <typename F, typename std::enable_if<!std::is_pointer<F>::value>::type*& = enabler> template <typename F, typename std::enable_if<std::is_null_pointer<F>::value>::type*& = enabler>
Action(F fn) {}
template <typename F, typename std::enable_if<!std::is_pointer<F>::value && !std::is_null_pointer<F>::value>::type*& = enabler>
void operator=(F fn) { void operator=(F fn) {
fn_ = make_adaptor(fn, &F::operator()); fn_ = make_adaptor(fn, &F::operator());
} }
@ -205,6 +217,9 @@ public:
fn_ = make_adaptor(fn, fn); fn_ = make_adaptor(fn, fn);
} }
template <typename F, typename std::enable_if<std::is_null_pointer<F>::value>::type*& = enabler>
void operator=(F fn) {}
operator bool() const { operator bool() const {
return (bool)fn_; return (bool)fn_;
} }

View File

@ -131,7 +131,7 @@ TEST_CASE("Simple calculator test", "[general]")
parser["Additive"] = { parser["Additive"] = {
// Default action // Default action
[]() {}, nullptr,
// Action for the first choice // Action for the first choice
[](const vector<Any>& v) { return v[0].get<int>() + v[1].get<int>(); }, [](const vector<Any>& v) { return v[0].get<int>() + v[1].get<int>(); },
// Action for the second choice // Action for the second choice
@ -139,7 +139,7 @@ TEST_CASE("Simple calculator test", "[general]")
}; };
parser["Multitive"] = [](const vector<Any>& v) { parser["Multitive"] = [](const vector<Any>& v) {
return v.size() == 1 ? v[0] : v[0].get<int>() * v[1].get<int>(); return v.size() == 1 ? int(v[0]) : v[0].get<int>() * v[1].get<int>();
}; };
parser["Primary"] = [](const vector<Any>& v) { parser["Primary"] = [](const vector<Any>& v) {