Changed the semantic values interface.

This commit is contained in:
yhirose 2015-02-21 19:38:30 -05:00
parent cf574074c4
commit 3d3af85bc7
5 changed files with 246 additions and 305 deletions

View File

@ -40,24 +40,24 @@ int main(void) {
// (3) Setup an action // (3) Setup an action
parser["Additive"] = { parser["Additive"] = {
nullptr, // Default action nullptr, // Default action
[](const vector<any>& v) { [](const SemanticValues& sv) {
return v[0].get<int>() + v[1].get<int>(); // 1st choice return sv[0].val.get<int>() + sv[1].val.get<int>(); // 1st choice
}, },
[](const vector<any>& v) { return v[0]; } // 2nd choice [](const SemanticValues& sv) { return sv[0]; } // 2nd choice
}; };
parser["Multitive"] = { parser["Multitive"] = {
nullptr, // Default action nullptr, // Default action
[](const vector<any>& v) { [](const SemanticValues& sv) {
return v[0].get<int>() * v[1].get<int>(); // 1st choice return sv[0].val.get<int>() * sv[1].val.get<int>(); // 1st choice
}, },
[](const vector<any>& v) { return v[0]; } // 2nd choice [](const SemanticValues& sv) { return sv[0]; } // 2nd choice
}; };
/* This action is not necessary. /* This action is not necessary.
parser["Primary"] = [](const vector<any>& v) { parser["Primary"] = [](const SemanticValues& sv) {
return v[0]; return sv[0];
}; };
*/ */
@ -76,34 +76,35 @@ int main(void) {
Here is a complete list of available actions: Here is a complete list of available actions:
```c++ ```c++
[](const char* s, size_t l, const std::vector<peglib::any>& v, any& c) [](const SemanticValues& sv, any& dt)
[](const char* s, size_t l, const std::vector<peglib::any>& v) [](const SemanticValues& sv)
[](const char* s, size_t l) [](const char* s, size_t l)
[](const std::vector<peglib::any>& v, any& c)
[](const std::vector<peglib::any>& v)
[]() []()
[](const SemanticValues& v, any& c)
[](const SemanticValues& v)
``` ```
`const char* s, size_t l` gives a pointer and length of the matched string. `const SemanticValues& sv` contains semantic values. `SemanticValues` structure is defined as follows.
`const std::vector<peglib::any>& v` contains semantic values. `peglib::any` class is very similar to [boost::any](http://www.boost.org/doc/libs/1_57_0/doc/html/any.html). You can obtain a value by castning it to the actual type. In order to determine the actual type, you have to check the return value type of the child action for the semantic value.
`any& c` is a context data which can be used by the user for whatever purposes.
`const SemanticValues&` is also available. `SemanticValues` structure contains all of above information as well as the vector of definition names of semantic values.
```c++ ```c++
struct SemanticValues struct SemanticValue {
{ peglib::any val; // Semantic value
std::vector<any> values; // Semantic value std::string name; // Definition name for the sematic value
std::vector<std::string> names; // Definition name const char* s; // Token start for the semantic value
const char* s; // Token start size_t l; // Token length for the semantic value
size_t l; // Token length
}; };
struct SemanticValues : protected std::vector<SemanticValue>
{
const char* s; // Token start
size_t l; // Token length
}
``` ```
`peglib::any` class is very similar to [boost::any](http://www.boost.org/doc/libs/1_57_0/doc/html/any.html). You can obtain a value by castning it to the actual type. In order to determine the actual type, you have to check the return value type of the child action for the semantic value.
`const char* s, size_t l` gives a pointer and length of the matched string. This is same as `sv.s` and `sv.l`.
`any& dt` is a data object which can be used by the user for whatever purposes.
The following example uses `<` ... ` >` operators. They are the *anchor* operators. Each anchor operator creates a semantic value that contains `const char*` of the position. It could be useful to eliminate unnecessary characters. The following example uses `<` ... ` >` operators. They are the *anchor* operators. Each anchor operator creates a semantic value that contains `const char*` of the position. It could be useful to eliminate unnecessary characters.
```c++ ```c++
@ -115,7 +116,7 @@ auto syntax = R"(
peg pg(syntax); peg pg(syntax);
pg["TOKEN"] = [](const char* s, size_t l, const vector<any>& v) { pg["TOKEN"] = [](const char* s, size_t l) {
// 'token' doesn't include trailing whitespaces // 'token' doesn't include trailing whitespaces
auto token = string(s, l); auto token = string(s, l);
}; };
@ -132,8 +133,8 @@ peglib::peg parser(
" ~_ <- [ \t]* " " ~_ <- [ \t]* "
); );
parser["ROOT"] = [&](const vector<any>& v) { parser["ROOT"] = [&](const SemanticValues& sv) {
assert(v.size() == 2); // should be 2 instead of 5. assert(sv.size() == 2); // should be 2 instead of 5.
}; };
auto ret = parser.parse(" item1, item2 "); auto ret = parser.parse(" item1, item2 ");
@ -253,7 +254,7 @@ auto syntax = R"(
Rules rules = { Rules rules = {
{ {
"NAME", usr([](const char* s, size_t l, SemanticValues& v, any& c) { "NAME", usr([](const char* s, size_t l, SemanticValues& sv, any& c) {
static vector<string> names = { "PEG", "BNF" }; static vector<string> names = { "PEG", "BNF" };
for (const auto& n: names) { for (const auto& n: names) {
if (n.size() <= l && !n.compare(0, n.size(), s, n.size())) { if (n.size() <= l && !n.compare(0, n.size(), s, n.size())) {

View File

@ -32,11 +32,11 @@ int main(int argc, const char** argv)
const char* s = argv[1]; const char* s = argv[1];
auto reduce = [](const vector<any>& v) -> long { auto reduce = [](const SemanticValues& sv) -> long {
auto result = v[0].get<long>(); auto result = sv[0].val.get<long>();
for (auto i = 1u; i < v.size(); i += 2) { for (auto i = 1u; i < sv.size(); i += 2) {
auto num = v[i + 1].get<long>(); auto num = sv[i + 1].val.get<long>();
auto ope = v[i].get<char>(); auto ope = sv[i].val.get<char>();
switch (ope) { switch (ope) {
case '+': result += num; break; case '+': result += num; break;
case '-': result -= num; break; case '-': result -= num; break;

View File

@ -31,11 +31,11 @@ int main(int argc, const char** argv)
const char* s = argv[1]; const char* s = argv[1];
auto reduce = [](const vector<any>& v) -> long { auto reduce = [](const SemanticValues& sv) -> long {
auto result = v[0].get<long>(); auto result = sv[0].val.get<long>();
for (auto i = 1u; i < v.size(); i += 2) { for (auto i = 1u; i < sv.size(); i += 2) {
auto num = v[i + 1].get<long>(); auto num = sv[i + 1].val.get<long>();
auto ope = v[i].get<char>(); auto ope = sv[i].val.get<char>();
switch (ope) { switch (ope) {
case '+': result += num; break; case '+': result += num; break;
case '-': result -= num; break; case '-': result -= num; break;

422
peglib.h
View File

@ -152,27 +152,44 @@ private:
/* /*
* Semantic values * Semantic values
*/ */
struct SemanticValues struct SemanticValue {
any val;
std::string name;
const char* s;
size_t l;
};
struct SemanticValues : protected std::vector<SemanticValue>
{ {
std::vector<any> values; const char* s;
std::vector<std::string> names; size_t l;
const char* s;
size_t l;
SemanticValues() : s(nullptr), l(0) {} SemanticValues() : s(nullptr), l(0) {}
typedef SemanticValue T;
using std::vector<T>::size;
using std::vector<T>::empty;
using std::vector<T>::assign;
using std::vector<T>::begin;
using std::vector<T>::end;
using std::vector<T>::rbegin;
using std::vector<T>::rend;
using std::vector<T>::operator[];
using std::vector<T>::at;
using std::vector<T>::resize;
using std::vector<T>::front;
using std::vector<T>::back;
using std::vector<T>::push_back;
using std::vector<T>::pop_back;
using std::vector<T>::insert;
using std::vector<T>::erase;
using std::vector<T>::clear;
using std::vector<T>::swap;
}; };
/* /*
* Semantic action * Semantic action
*/ */
template <
typename R, typename F,
typename std::enable_if<!std::is_void<R>::value>::type*& = enabler,
typename... Args>
any call(F fn, Args&&... args) {
return any(fn(std::forward<Args>(args)...));
}
template < template <
typename R, typename F, typename R, typename F,
typename std::enable_if<std::is_void<R>::value>::type*& = enabler, typename std::enable_if<std::is_void<R>::value>::type*& = enabler,
@ -182,6 +199,30 @@ any call(F fn, Args&&... args) {
return any(); return any();
} }
template <
typename R, typename F,
typename std::enable_if<std::is_same<R, any>::value>::type*& = enabler,
typename... Args>
any call(F fn, Args&&... args) {
return fn(std::forward<Args>(args)...);
}
template <
typename R, typename F,
typename std::enable_if<std::is_same<R, SemanticValue>::value>::type*& = enabler,
typename... Args>
any call(F fn, Args&&... args) {
return fn(std::forward<Args>(args)...).val;
}
template <
typename R, typename F,
typename std::enable_if<!std::is_void<R>::value && !std::is_same<R, any>::value && !std::is_same<R, SemanticValue>::value>::type*& = enabler,
typename... Args>
any call(F fn, Args&&... args) {
return any(fn(std::forward<Args>(args)...));
}
class Action class Action
{ {
public: public:
@ -217,149 +258,81 @@ public:
return (bool)fn_; return (bool)fn_;
} }
any operator()(const SemanticValues& v, any& c) const { any operator()(const SemanticValues& sv, any& dt) const {
return fn_(v, c); return fn_(sv, dt);
} }
private: private:
template <typename R> template <typename R>
struct TypeAdaptor { struct TypeAdaptor {
TypeAdaptor(std::function<R (const SemanticValues& v)> fn) TypeAdaptor(std::function<R (const SemanticValues& sv)> fn)
: fn_(fn) {} : fn_(fn) {}
any operator()(const SemanticValues& v, any& c) { any operator()(const SemanticValues& sv, any& dt) {
return call<R>(fn_, v); return call<R>(fn_, sv);
} }
std::function<R (const SemanticValues& v)> fn_; std::function<R (const SemanticValues& sv)> fn_;
}; };
template <typename R> template <typename R>
struct TypeAdaptor_c { struct TypeAdaptor_c {
TypeAdaptor_c(std::function<R (const SemanticValues& v, any& c)> fn) TypeAdaptor_c(std::function<R (const SemanticValues& sv, any& dt)> fn)
: fn_(fn) {} : fn_(fn) {}
any operator()(const SemanticValues& v, any& c) { any operator()(const SemanticValues& sv, any& dt) {
return call<R>(fn_, v, c); return call<R>(fn_, sv, dt);
} }
std::function<R (const SemanticValues& v, any& c)> fn_; std::function<R (const SemanticValues& sv, any& dt)> fn_;
};
template <typename R>
struct TypeAdaptor_s_l_v_c {
TypeAdaptor_s_l_v_c(std::function<R (const char* s, size_t l, const std::vector<any>& v, any& c)> fn)
: fn_(fn) {}
any operator()(const SemanticValues& v, any& c) {
return call<R>(fn_, v.s, v.l, v.values, c);
}
std::function<R (const char* s, size_t l, const std::vector<any>& v, any& c)> fn_;
};
template <typename R>
struct TypeAdaptor_s_l_v {
TypeAdaptor_s_l_v(std::function<R (const char* s, size_t l, const std::vector<any>& v)> fn)
: fn_(fn) {}
any operator()(const SemanticValues& v, any& c) {
return call<R>(fn_, v.s, v.l, v.values);
}
std::function<R (const char* s, size_t l, const std::vector<any>& v)> fn_;
}; };
template <typename R> template <typename R>
struct TypeAdaptor_s_l { struct TypeAdaptor_s_l {
TypeAdaptor_s_l(std::function<R (const char* s, size_t l)> fn) : fn_(fn) {} TypeAdaptor_s_l(std::function<R (const char* s, size_t l)> fn) : fn_(fn) {}
any operator()(const SemanticValues& v, any& c) { any operator()(const SemanticValues& sv, any& dt) {
return call<R>(fn_, v.s, v.l); return call<R>(fn_, sv.s, sv.l);
} }
std::function<R (const char* s, size_t l)> fn_; std::function<R (const char* s, size_t l)> fn_;
}; };
template <typename R>
struct TypeAdaptor_v_n {
TypeAdaptor_v_n(std::function<R (const std::vector<any>& v, any& c)> fn) : fn_(fn) {}
any operator()(const SemanticValues& v, any& c) {
return call<R>(fn_, v.values, c);
}
std::function<R (const std::vector<any>& v, any& c)> fn_;
};
template <typename R>
struct TypeAdaptor_v {
TypeAdaptor_v(std::function<R (const std::vector<any>& v)> fn) : fn_(fn) {}
any operator()(const SemanticValues& v, any& c) {
return call<R>(fn_, v.values);
}
std::function<R (const std::vector<any>& v)> fn_;
};
template <typename R> template <typename R>
struct TypeAdaptor_empty { struct TypeAdaptor_empty {
TypeAdaptor_empty(std::function<R ()> fn) : fn_(fn) {} TypeAdaptor_empty(std::function<R ()> fn) : fn_(fn) {}
any operator()(const SemanticValues& v, any& c) { any operator()(const SemanticValues& sv, any& dt) {
return call<R>(fn_); return call<R>(fn_);
} }
std::function<R ()> fn_; std::function<R ()> fn_;
}; };
typedef std::function<any (const SemanticValues& v, any& c)> Fty; typedef std::function<any (const SemanticValues& sv, any& dt)> Fty;
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& v) const) { Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv) const) {
return TypeAdaptor<R>(fn); return TypeAdaptor<R>(fn);
} }
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& v)) { Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv)) {
return TypeAdaptor<R>(fn); return TypeAdaptor<R>(fn);
} }
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R(*mf)(const SemanticValues& v)) { Fty make_adaptor(F fn, R(*mf)(const SemanticValues& sv)) {
return TypeAdaptor<R>(fn); return TypeAdaptor<R>(fn);
} }
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& v, any& c) const) { Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv, any& dt) const) {
return TypeAdaptor_c<R>(fn); return TypeAdaptor_c<R>(fn);
} }
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& v, any& c)) { Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv, any& dt)) {
return TypeAdaptor_c<R>(fn); return TypeAdaptor_c<R>(fn);
} }
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R(*mf)(const SemanticValues& v, any& c)) { Fty make_adaptor(F fn, R(*mf)(const SemanticValues& sv, any& dt)) {
return TypeAdaptor_c<R>(fn); return TypeAdaptor_c<R>(fn);
} }
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t, const std::vector<any>& v, any& c) const) {
return TypeAdaptor_s_l_v_c<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t, const std::vector<any>& v, any& c)) {
return TypeAdaptor_s_l_v_c<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R(*mf)(const char*, size_t, const std::vector<any>& v, any& c)) {
return TypeAdaptor_s_l_v_c<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t, const std::vector<any>& v) const) {
return TypeAdaptor_s_l_v<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t, const std::vector<any>& v)) {
return TypeAdaptor_s_l_v<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R(*mf)(const char*, size_t, const std::vector<any>& v)) {
return TypeAdaptor_s_l_v<R>(fn);
}
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t) const) { Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t) const) {
return TypeAdaptor_s_l<R>(fn); return TypeAdaptor_s_l<R>(fn);
@ -375,36 +348,6 @@ private:
return TypeAdaptor_s_l<R>(fn); return TypeAdaptor_s_l<R>(fn);
} }
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const std::vector<any>& v, any& c) const) {
return TypeAdaptor_v_n<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const std::vector<any>& v, any& c)) {
return TypeAdaptor_v_n<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (*mf)(const std::vector<any>& v, any& c)) {
return TypeAdaptor_v_n<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const std::vector<any>& v) const) {
return TypeAdaptor_v<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)(const std::vector<any>& v)) {
return TypeAdaptor_v<R>(fn);
}
template<typename F, typename R>
Fty make_adaptor(F fn, R (*mf)(const std::vector<any>& v)) {
return TypeAdaptor_v<R>(fn);
}
template<typename F, typename R> template<typename F, typename R>
Fty make_adaptor(F fn, R (F::*mf)() const) { Fty make_adaptor(F fn, R (F::*mf)() const) {
return TypeAdaptor_empty<R>(fn); return TypeAdaptor_empty<R>(fn);
@ -455,7 +398,7 @@ class Ope
{ {
public: public:
virtual ~Ope() {}; virtual ~Ope() {};
virtual Result parse(const char* s, size_t l, SemanticValues& v, any& c) const = 0; virtual Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const = 0;
}; };
class Sequence : public Ope class Sequence : public Ope
@ -482,11 +425,11 @@ public:
Sequence(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {} Sequence(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {}
Sequence(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(std::move(opes)) {} Sequence(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(std::move(opes)) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
size_t i = 0; size_t i = 0;
for (const auto& ope : opes_) { for (const auto& ope : opes_) {
const auto& rule = *ope; const auto& rule = *ope;
auto r = rule.parse(s + i, l - i, v, c); auto r = rule.parse(s + i, l - i, sv, dt);
if (!r.ret) { if (!r.ret) {
auto err = r.err; auto err = r.err;
if (err.empty()) { if (err.empty()) {
@ -525,20 +468,18 @@ public:
PrioritizedChoice(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {} PrioritizedChoice(const std::vector<std::shared_ptr<Ope>>& opes) : opes_(opes) {}
PrioritizedChoice(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(std::move(opes)) {} PrioritizedChoice(std::vector<std::shared_ptr<Ope>>&& opes) : opes_(std::move(opes)) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
size_t id = 0; size_t id = 0;
for (const auto& ope : opes_) { for (const auto& ope : opes_) {
const auto& rule = *ope; const auto& rule = *ope;
SemanticValues chldsv; SemanticValues chldsv;
auto r = rule.parse(s, l, chldsv, c); auto r = rule.parse(s, l, chldsv, dt);
if (r.ret) { if (r.ret) {
assert(chldsv.values.size() == chldsv.names.size()); if (!chldsv.empty()) {
if (!chldsv.values.empty()) { sv.insert(sv.end(), chldsv.begin(), chldsv.end());
v.values.insert(v.values.end(), chldsv.values.begin(), chldsv.values.end());
v.names.insert(v.names.end(), chldsv.names.begin(), chldsv.names.end());
} }
v.s = chldsv.s; sv.s = chldsv.s;
v.l = chldsv.l; sv.l = chldsv.l;
return success(r.len, id); return success(r.len, id);
} }
id++; id++;
@ -557,11 +498,11 @@ class ZeroOrMore : public Ope
public: public:
ZeroOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {} ZeroOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
auto i = 0; auto i = 0;
while (l - i > 0) { while (l - i > 0) {
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s + i, l - i, v, c); auto r = rule.parse(s + i, l - i, sv, dt);
if (!r.ret) { if (!r.ret) {
break; break;
} }
@ -579,9 +520,9 @@ class OneOrMore : public Ope
public: public:
OneOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {} OneOrMore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s, l, v, c); auto r = rule.parse(s, l, sv, dt);
if (!r.ret) { if (!r.ret) {
auto err = r.err; auto err = r.err;
if (err.empty()) { if (err.empty()) {
@ -592,7 +533,7 @@ public:
auto i = r.len; auto i = r.len;
while (l - i > 0) { while (l - i > 0) {
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s + i, l - i, v, c); auto r = rule.parse(s + i, l - i, sv, dt);
if (!r.ret) { if (!r.ret) {
break; break;
} }
@ -610,9 +551,9 @@ class Option : public Ope
public: public:
Option(const std::shared_ptr<Ope>& ope) : ope_(ope) {} Option(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s, l, v, c); auto r = rule.parse(s, l, sv, dt);
return success(r.ret ? r.len : 0); return success(r.ret ? r.len : 0);
} }
@ -625,9 +566,9 @@ class AndPredicate : public Ope
public: public:
AndPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {} AndPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s, l, v, c); auto r = rule.parse(s, l, sv, dt);
if (r.ret) { if (r.ret) {
return success(0); return success(0);
} else { } else {
@ -644,9 +585,9 @@ class NotPredicate : public Ope
public: public:
NotPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {} NotPredicate(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s, l, v, c); auto r = rule.parse(s, l, sv, dt);
if (r.ret) { if (r.ret) {
return fail(s); return fail(s);
} else { } else {
@ -663,7 +604,7 @@ class LiteralString : public Ope
public: public:
LiteralString(const std::string& s) : lit_(s) {} LiteralString(const std::string& s) : lit_(s) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
auto i = 0u; auto i = 0u;
for (; i < lit_.size(); i++) { for (; i < lit_.size(); i++) {
if (i >= l || s[i] != lit_[i]) { if (i >= l || s[i] != lit_[i]) {
@ -682,7 +623,7 @@ class CharacterClass : public Ope
public: public:
CharacterClass(const std::string& chars) : chars_(chars) {} CharacterClass(const std::string& chars) : chars_(chars) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
// TODO: UTF8 support // TODO: UTF8 support
if (l < 1) { if (l < 1) {
return fail(s); return fail(s);
@ -714,7 +655,7 @@ class Character : public Ope
public: public:
Character(char ch) : ch_(ch) {} Character(char ch) : ch_(ch) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
// TODO: UTF8 support // TODO: UTF8 support
if (l < 1 || s[0] != ch_) { if (l < 1 || s[0] != ch_) {
return fail(s); return fail(s);
@ -729,7 +670,7 @@ private:
class AnyCharacter : public Ope class AnyCharacter : public Ope
{ {
public: public:
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
// TODO: UTF8 support // TODO: UTF8 support
if (l < 1) { if (l < 1) {
return fail(s); return fail(s);
@ -745,10 +686,10 @@ public:
Capture(const std::shared_ptr<Ope>& ope, MatchAction ma, size_t ci) Capture(const std::shared_ptr<Ope>& ope, MatchAction ma, size_t ci)
: ope_(ope), match_action_(ma), capture_id(ci) {} : ope_(ope), match_action_(ma), capture_id(ci) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
assert(ope_); assert(ope_);
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s, l, v, c); auto r = rule.parse(s, l, sv, dt);
if (r.ret && match_action_) { if (r.ret && match_action_) {
match_action_(s, r.len, capture_id); match_action_(s, r.len, capture_id);
} }
@ -766,13 +707,13 @@ class Anchor : public Ope
public: public:
Anchor(const std::shared_ptr<Ope>& ope) : ope_(ope) {} Anchor(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
assert(ope_); assert(ope_);
const auto& rule = *ope_; const auto& rule = *ope_;
auto r = rule.parse(s, l, v, c); auto r = rule.parse(s, l, sv, dt);
if (r.ret) { if (r.ret) {
v.s = s; sv.s = s;
v.l = r.len; sv.l = r.len;
} }
return r; return r;
} }
@ -781,20 +722,20 @@ private:
std::shared_ptr<Ope> ope_; std::shared_ptr<Ope> ope_;
}; };
typedef std::function<Result (const char* s, size_t l, SemanticValues& v, any& c)> Parser; typedef std::function<Result (const char* s, size_t l, SemanticValues& sv, any& dt)> Parser;
class User : public Ope class User : public Ope
{ {
public: public:
User(Parser fn) : fn_(fn) {} User(Parser fn) : fn_(fn) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
assert(fn_); assert(fn_);
return fn_(s, l, v, c); return fn_(s, l, sv, dt);
} }
private: private:
std::function<Result (const char* s, size_t l, SemanticValues& v, any& c)> fn_; std::function<Result (const char* s, size_t l, SemanticValues& sv, any& dt)> fn_;
}; };
class WeakHolder : public Ope class WeakHolder : public Ope
@ -802,11 +743,11 @@ class WeakHolder : public Ope
public: public:
WeakHolder(const std::shared_ptr<Ope>& ope) : weak_(ope) {} WeakHolder(const std::shared_ptr<Ope>& ope) : weak_(ope) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
auto ope = weak_.lock(); auto ope = weak_.lock();
assert(ope); assert(ope);
const auto& rule = *ope; const auto& rule = *ope;
return rule.parse(s, l, v, c); return rule.parse(s, l, sv, dt);
} }
private: private:
@ -859,17 +800,17 @@ public:
return *this; return *this;
} }
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
return holder_->parse(s, l, v, c); return holder_->parse(s, l, sv, dt);
} }
template <typename T> template <typename T>
Result parse(const char* s, size_t l, T& val) const { Result parse(const char* s, size_t l, T& val) const {
SemanticValues v; SemanticValues sv;
any c; any dt;
auto r = holder_->parse(s, l, v, c); auto r = holder_->parse(s, l, sv, dt);
if (r.ret && !v.values.empty() && !v.values.front().is_undefined()) { if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) {
val = v.values[0].get<T>(); val = sv[0].val.get<T>();
} }
return r; return r;
} }
@ -882,9 +823,9 @@ public:
Result parse(const char* s) const { Result parse(const char* s) const {
auto l = strlen(s); auto l = strlen(s);
SemanticValues v; SemanticValues sv;
any c; any dt;
return holder_->parse(s, l, v, c); return holder_->parse(s, l, sv, dt);
} }
Definition& operator=(Action ac) { Definition& operator=(Action ac) {
@ -922,14 +863,14 @@ private:
Holder(Definition* outer) Holder(Definition* outer)
: outer_(outer) {} : outer_(outer) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
if (!ope_) { if (!ope_) {
throw std::logic_error("Uninitialized definition ope was used..."); throw std::logic_error("Uninitialized definition ope was used...");
} }
const auto& rule = *ope_; const auto& rule = *ope_;
SemanticValues chldsv; SemanticValues chldsv;
auto r = rule.parse(s, l, chldsv, c); auto r = rule.parse(s, l, chldsv, dt);
if (r.ret && !outer_->ignore) { if (r.ret && !outer_->ignore) {
assert(!outer_->actions.empty()); assert(!outer_->actions.empty());
@ -942,10 +883,9 @@ private:
chldsv.s = s; chldsv.s = s;
chldsv.l = r.len; chldsv.l = r.len;
} }
auto val = reduce(chldsv, c, action); auto val = reduce(chldsv, dt, action);
v.values.push_back(val); sv.push_back(SemanticValue{ val, outer_->name, nullptr, 0 });
v.names.push_back(outer_->name);
} }
return r; return r;
} }
@ -953,13 +893,13 @@ private:
private: private:
friend class Definition; friend class Definition;
any reduce(const SemanticValues& v, any& c, const Action& action) const { any reduce(const SemanticValues& sv, any& dt, const Action& action) const {
if (action) { if (action) {
return action(v, c); return action(sv, dt);
} else if (v.values.empty()) { } else if (sv.empty()) {
return any(); return any();
} else { } else {
return v.values.front(); return sv.front().val;
} }
} }
@ -981,9 +921,9 @@ public:
: grammar_(grammar) : grammar_(grammar)
, name_(name) {} , name_(name) {}
Result parse(const char* s, size_t l, SemanticValues& v, any& c) const { Result parse(const char* s, size_t l, SemanticValues& sv, any& dt) const {
const auto& rule = *grammar_.at(name_).holder_; const auto& rule = *grammar_.at(name_).holder_;
return rule.parse(s, l, v, c); return rule.parse(s, l, sv, dt);
} }
private: private:
@ -1034,8 +974,8 @@ inline std::shared_ptr<Ope> cls(const std::string& chars) {
return std::make_shared<CharacterClass>(chars); return std::make_shared<CharacterClass>(chars);
} }
inline std::shared_ptr<Ope> chr(char c) { inline std::shared_ptr<Ope> chr(char dt) {
return std::make_shared<Character>(c); return std::make_shared<Character>(dt);
} }
inline std::shared_ptr<Ope> dot() { inline std::shared_ptr<Ope> dot() {
@ -1054,7 +994,7 @@ inline std::shared_ptr<Ope> anc(const std::shared_ptr<Ope>& ope) {
return std::make_shared<Anchor>(ope); return std::make_shared<Anchor>(ope);
} }
inline std::shared_ptr<Ope> usr(std::function<Result (const char* s, size_t l, SemanticValues& v, any& c)> fn) { inline std::shared_ptr<Ope> usr(std::function<Result (const char* s, size_t l, SemanticValues& sv, any& dt)> fn) {
return std::make_shared<User>(fn); return std::make_shared<User>(fn);
} }
@ -1206,14 +1146,14 @@ private:
} }
void setup_actions() { void setup_actions() {
g["Definition"] = [&](const std::vector<any>& v, any& c) { g["Definition"] = [&](const SemanticValues& sv, any& dt) {
Context& cxt = *c.get<Context*>(); Context& cxt = *dt.get<Context*>();
auto ignore = (v.size() == 4); auto ignore = (sv.size() == 4);
auto baseId = ignore ? 1 : 0; auto baseId = ignore ? 1 : 0;
const auto& name = v[baseId].get<std::string>(); const auto& name = sv[baseId].val.get<std::string>();
auto ope = v[baseId + 2].get<std::shared_ptr<Ope>>(); auto ope = sv[baseId + 2].val.get<std::shared_ptr<Ope>>();
auto& def = (*cxt.grammar)[name]; auto& def = (*cxt.grammar)[name];
def <= ope; def <= ope;
@ -1225,40 +1165,40 @@ private:
} }
}; };
g["Expression"] = [&](const std::vector<any>& v) { g["Expression"] = [&](const SemanticValues& sv) {
if (v.size() == 1) { if (sv.size() == 1) {
return v[0].get<std::shared_ptr<Ope>>(); return sv[0].val.get<std::shared_ptr<Ope>>();
} else { } else {
std::vector<std::shared_ptr<Ope>> opes; std::vector<std::shared_ptr<Ope>> opes;
for (auto i = 0u; i < v.size(); i++) { for (auto i = 0u; i < sv.size(); i++) {
opes.push_back(v[i].get<std::shared_ptr<Ope>>()); opes.push_back(sv[i].val.get<std::shared_ptr<Ope>>());
} }
const std::shared_ptr<Ope> ope = std::make_shared<PrioritizedChoice>(opes); const std::shared_ptr<Ope> ope = std::make_shared<PrioritizedChoice>(opes);
return ope; return ope;
} }
}; };
g["Sequence"] = [&](const std::vector<any>& v) { g["Sequence"] = [&](const SemanticValues& sv) {
if (v.size() == 1) { if (sv.size() == 1) {
return v[0].get<std::shared_ptr<Ope>>(); return sv[0].val.get<std::shared_ptr<Ope>>();
} else { } else {
std::vector<std::shared_ptr<Ope>> opes; std::vector<std::shared_ptr<Ope>> opes;
for (const auto& x: v) { for (const auto& x: sv) {
opes.push_back(x.get<std::shared_ptr<Ope>>()); opes.push_back(x.val.get<std::shared_ptr<Ope>>());
} }
const std::shared_ptr<Ope> ope = std::make_shared<Sequence>(opes); const std::shared_ptr<Ope> ope = std::make_shared<Sequence>(opes);
return ope; return ope;
} }
}; };
g["Prefix"] = [&](const std::vector<any>& v, any& c) { g["Prefix"] = [&](const SemanticValues& sv, any& dt) {
std::shared_ptr<Ope> ope; std::shared_ptr<Ope> ope;
if (v.size() == 1) { if (sv.size() == 1) {
ope = v[0].get<std::shared_ptr<Ope>>(); ope = sv[0].val.get<std::shared_ptr<Ope>>();
} else { } else {
assert(v.size() == 2); assert(sv.size() == 2);
auto tok = v[0].get<char>(); auto tok = sv[0].val.get<char>();
ope = v[1].get<std::shared_ptr<Ope>>(); ope = sv[1].val.get<std::shared_ptr<Ope>>();
if (tok == '&') { if (tok == '&') {
ope = apd(ope); ope = apd(ope);
} else { // '!' } else { // '!'
@ -1268,13 +1208,13 @@ private:
return ope; return ope;
}; };
g["Suffix"] = [&](const std::vector<any>& v, any& c) { g["Suffix"] = [&](const SemanticValues& sv, any& dt) {
auto ope = v[0].get<std::shared_ptr<Ope>>(); auto ope = sv[0].val.get<std::shared_ptr<Ope>>();
if (v.size() == 1) { if (sv.size() == 1) {
return ope; return ope;
} else { } else {
assert(v.size() == 2); assert(sv.size() == 2);
auto tok = v[1].get<char>(); auto tok = sv[1].val.get<char>();
if (tok == '?') { if (tok == '?') {
return opt(ope); return opt(ope);
} else if (tok == '*') { } else if (tok == '*') {
@ -1286,27 +1226,27 @@ private:
}; };
g["Primary"].actions = { g["Primary"].actions = {
[&](const std::vector<any>& v) { [&](const SemanticValues& sv) {
return v[0]; return sv[0];
}, },
[&](const char* s, size_t l, const std::vector<any>& v, any& c) { [&](const SemanticValues& sv, any& dt) {
Context& cxt = *c.get<Context*>(); Context& cxt = *dt.get<Context*>();
const auto& ident = v[0].get<std::string>(); const auto& ident = sv[0].val.get<std::string>();
cxt.references[ident] = s; // for error handling cxt.references[ident] = sv.s; // for error handling
return ref(*cxt.grammar, ident); return ref(*cxt.grammar, ident);
}, },
[&](const std::vector<any>& v) { [&](const SemanticValues& sv) {
return v[1]; return sv[1];
}, },
// Anchor // Anchor
[&](const std::vector<any>& v) { [&](const SemanticValues& sv) {
auto ope = v[1].get<std::shared_ptr<Ope>>(); auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
return anc(ope); return anc(ope);
}, },
// Capture // Capture
[&](const std::vector<any>& v, any& c) { [&](const SemanticValues& sv, any& dt) {
Context& cxt = *c.get<Context*>(); Context& cxt = *dt.get<Context*>();
auto ope = v[1].get<std::shared_ptr<Ope>>(); auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
return cap(ope, cxt.match_action, ++cxt.capture_count); return cap(ope, cxt.match_action, ++cxt.capture_count);
} }
}; };
@ -1341,9 +1281,9 @@ private:
Context cxt; Context cxt;
cxt.match_action = ma; cxt.match_action = ma;
SemanticValues v; SemanticValues sv;
any c = &cxt; any dt = &cxt;
auto r = g["Grammar"].parse(s, l, v, c); auto r = g["Grammar"].parse(s, l, sv, dt);
if (!r.ret) { if (!r.ret) {
if (log) { if (log) {
@ -1398,7 +1338,7 @@ private:
for (auto i = 0u; i < l; i++) { for (auto i = 0u; i < l; i++) {
auto ch = s[i]; auto ch = s[i];
if (ch == '\\') { if (ch == '\\') {
i++; i++;
switch (s[i]) { switch (s[i]) {
case 'n': r += '\n'; break; case 'n': r += '\n'; break;
case 'r': r += '\r'; break; case 'r': r += '\r'; break;
@ -1556,11 +1496,11 @@ struct match
std::string str() const { return std::string(s, l); } std::string str() const { return std::string(s, l); }
}; };
std::vector<Item> matches; std::vector<Item> matches;
typedef std::vector<Item>::iterator iterator; typedef std::vector<Item>::iterator iterator;
typedef std::vector<Item>::const_iterator const_iterator; typedef std::vector<Item>::const_iterator const_iterator;
bool empty() const { bool empty() const {
return matches.empty(); return matches.empty();
} }
@ -1584,15 +1524,15 @@ struct match
iterator begin() { iterator begin() {
return matches.begin(); return matches.begin();
} }
iterator end() { iterator end() {
return matches.end(); return matches.end();
} }
const_iterator begin() const { const_iterator begin() const {
return matches.cbegin(); return matches.cbegin();
} }
const_iterator end() const { const_iterator end() const {
return matches.cend(); return matches.cend();
} }

View File

@ -155,8 +155,8 @@ TEST_CASE("Skip token test", "[general]")
" ~_ <- [ \t]* " " ~_ <- [ \t]* "
); );
parser["ROOT"] = [&](const vector<any>& v) { parser["ROOT"] = [&](const SemanticValues& sv) {
REQUIRE(v.size() == 2); REQUIRE(sv.size() == 2);
}; };
auto ret = parser.parse(" item1, item2 "); auto ret = parser.parse(" item1, item2 ");
@ -209,13 +209,13 @@ TEST_CASE("Simple calculator test", "[general]")
// Default action // Default action
nullptr, 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 SemanticValues& sv) { return sv[0].val.get<int>() + sv[1].val.get<int>(); },
// Action for the second choice // Action for the second choice
[](const vector<any>& v) { return v[0]; } [](const SemanticValues& sv) { return sv[0]; }
}; };
parser["Multitive"] = [](const vector<any>& v) { parser["Multitive"] = [](const SemanticValues& sv) {
return v.size() == 1 ? v[0].get<int>() : v[0].get<int>() * v[1].get<int>(); return sv.size() == 1 ? sv[0].val.get<int>() : sv[0].val.get<int>() * sv[1].val.get<int>();
}; };
parser["Number"] = [](const char* s, size_t l) { parser["Number"] = [](const char* s, size_t l) {
@ -241,11 +241,11 @@ TEST_CASE("Calculator test", "[general]")
NUMBER <= oom(cls("0-9")); NUMBER <= oom(cls("0-9"));
// Setup actions // Setup actions
auto reduce = [](const vector<any>& v) -> long { auto reduce = [](const SemanticValues& sv) -> long {
long ret = v[0].get<long>(); long ret = sv[0].val.get<long>();
for (auto i = 1u; i < v.size(); i += 2) { for (auto i = 1u; i < sv.size(); i += 2) {
auto num = v[i + 1].get<long>(); auto num = sv[i + 1].val.get<long>();
switch (v[i].get<char>()) { switch (sv[i].val.get<char>()) {
case '+': ret += num; break; case '+': ret += num; break;
case '-': ret -= num; break; case '-': ret -= num; break;
case '*': ret *= num; break; case '*': ret *= num; break;
@ -287,11 +287,11 @@ TEST_CASE("Calculator test2", "[general]")
auto& g = *grammar; auto& g = *grammar;
// Setup actions // Setup actions
auto reduce = [](const vector<any>& v) -> long { auto reduce = [](const SemanticValues& sv) -> long {
long ret = v[0].get<long>(); long ret = sv[0].val.get<long>();
for (auto i = 1u; i < v.size(); i += 2) { for (auto i = 1u; i < sv.size(); i += 2) {
auto num = v[i + 1].get<long>(); auto num = sv[i + 1].val.get<long>();
switch (v[i].get<char>()) { switch (sv[i].val.get<char>()) {
case '+': ret += num; break; case '+': ret += num; break;
case '-': ret -= num; break; case '-': ret -= num; break;
case '*': ret *= num; break; case '*': ret *= num; break;
@ -328,11 +328,11 @@ TEST_CASE("Calculator test3", "[general]")
" NUMBER <- [0-9]+ " " NUMBER <- [0-9]+ "
); );
auto reduce = [](const vector<any>& v) -> long { auto reduce = [](const SemanticValues& sv) -> long {
long ret = v[0].get<long>(); long ret = sv[0].val.get<long>();
for (auto i = 1u; i < v.size(); i += 2) { for (auto i = 1u; i < sv.size(); i += 2) {
auto num = v[i + 1].get<long>(); auto num = sv[i + 1].val.get<long>();
switch (v[i].get<char>()) { switch (sv[i].val.get<char>()) {
case '+': ret += num; break; case '+': ret += num; break;
case '-': ret -= num; break; case '-': ret -= num; break;
case '*': ret *= num; break; case '*': ret *= num; break;