mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Changed to allow simpler notation in actions.
This commit is contained in:
parent
8acb0e2822
commit
4202e6d111
@ -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, ...).
|
||||
|
||||
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:
|
||||
|
||||
|
35
peglib.h
35
peglib.h
@ -115,15 +115,24 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const std::string&() const {
|
||||
return get<std::string>();
|
||||
}
|
||||
|
||||
operator std::string&() {
|
||||
return get<std::string>();
|
||||
}
|
||||
|
||||
// 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:
|
||||
struct placeholder {
|
||||
@ -189,13 +198,16 @@ public:
|
||||
|
||||
//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())) {}
|
||||
|
||||
template <typename F, typename std::enable_if<std::is_pointer<F>::value>::type*& = enabler>
|
||||
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) {
|
||||
fn_ = make_adaptor(fn, &F::operator());
|
||||
}
|
||||
@ -205,6 +217,9 @@ public:
|
||||
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 {
|
||||
return (bool)fn_;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ TEST_CASE("Simple calculator test", "[general]")
|
||||
|
||||
parser["Additive"] = {
|
||||
// Default action
|
||||
[]() {},
|
||||
nullptr,
|
||||
// Action for the first choice
|
||||
[](const vector<Any>& v) { return v[0].get<int>() + v[1].get<int>(); },
|
||||
// Action for the second choice
|
||||
@ -139,7 +139,7 @@ TEST_CASE("Simple calculator test", "[general]")
|
||||
};
|
||||
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user