mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Name refactoring.
This commit is contained in:
parent
59f350673c
commit
e30b4a281f
36
README.md
36
README.md
@ -48,7 +48,7 @@ int main(void) {
|
|||||||
parser["Additive"] = {
|
parser["Additive"] = {
|
||||||
nullptr, // Default action
|
nullptr, // Default action
|
||||||
[](const SemanticValues& sv) {
|
[](const SemanticValues& sv) {
|
||||||
return sv[0].val.get<int>() + sv[1].val.get<int>(); // 1st choice
|
return sv[0].get<int>() + sv[1].get<int>(); // 1st choice
|
||||||
},
|
},
|
||||||
[](const SemanticValues& sv) { return sv[0]; } // 2nd choice
|
[](const SemanticValues& sv) { return sv[0]; } // 2nd choice
|
||||||
};
|
};
|
||||||
@ -56,19 +56,19 @@ int main(void) {
|
|||||||
parser["Multitive"] = [](const SemanticValues& sv) {
|
parser["Multitive"] = [](const SemanticValues& sv) {
|
||||||
switch (sv.choice) {
|
switch (sv.choice) {
|
||||||
case 0: // 1st choice
|
case 0: // 1st choice
|
||||||
return sv[0].val.get<int>() * sv[1].val.get<int>();
|
return sv[0].get<int>() * sv[1].get<int>();
|
||||||
default: // 2nd choice
|
default: // 2nd choice
|
||||||
return sv[0].val.get<int>();
|
return sv[0].get<int>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser["Number"] = [](const char* s, size_t l) {
|
parser["Number"] = [](const char* s, size_t n) {
|
||||||
return stoi(string(s, l), nullptr, 10);
|
return stoi(string(s, n), nullptr, 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
// (4) Parse
|
// (4) Parse
|
||||||
int val;
|
int val;
|
||||||
parser.parse_with_value("(1+2)*3", val);
|
parser.parse("(1+2)*3", val);
|
||||||
|
|
||||||
assert(val == 9);
|
assert(val == 9);
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ Here is a complete list of available actions:
|
|||||||
```c++
|
```c++
|
||||||
[](const SemanticValues& sv, any& dt)
|
[](const SemanticValues& sv, any& dt)
|
||||||
[](const SemanticValues& sv)
|
[](const SemanticValues& sv)
|
||||||
[](const char* s, size_t l)
|
[](const char* s, size_t n)
|
||||||
[]()
|
[]()
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -90,20 +90,20 @@ struct SemanticValue {
|
|||||||
peglib::any val; // Semantic value
|
peglib::any val; // Semantic value
|
||||||
std::string name; // Definition name for the sematic value
|
std::string name; // Definition name for the sematic value
|
||||||
const char* s; // Token start for the semantic value
|
const char* s; // Token start for the semantic value
|
||||||
size_t l; // Token length for the semantic value
|
size_t n; // Token length for the semantic value
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SemanticValues : protected std::vector<SemanticValue>
|
struct SemanticValues : protected std::vector<SemanticValue>
|
||||||
{
|
{
|
||||||
const char* s; // Token start
|
const char* s; // Token start
|
||||||
size_t l; // Token length
|
size_t n; // Token length
|
||||||
size_t choice; // Choice number (0 based index)
|
size_t choice; // Choice number (0 based index)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`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.
|
`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`.
|
`const char* s, size_t n` gives a pointer and length of the matched string. This is same as `sv.s` and `sv.n`.
|
||||||
|
|
||||||
`any& dt` is a data object which can be used by the user for whatever purposes.
|
`any& dt` is a data object which can be used by the user for whatever purposes.
|
||||||
|
|
||||||
@ -118,9 +118,9 @@ auto syntax = R"(
|
|||||||
|
|
||||||
peg pg(syntax);
|
peg pg(syntax);
|
||||||
|
|
||||||
pg["TOKEN"] = [](const char* s, size_t l) {
|
pg["TOKEN"] = [](const char* s, size_t n) {
|
||||||
// 'token' doesn't include trailing whitespaces
|
// 'token' doesn't include trailing whitespaces
|
||||||
auto token = string(s, l);
|
auto token = string(s, n);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ret = pg.parse(" token1, token2 ");
|
auto ret = pg.parse(" token1, token2 ");
|
||||||
@ -181,9 +181,9 @@ auto s = " [tag1] [tag2] [tag3] ";
|
|||||||
// peglib::peg_search
|
// peglib::peg_search
|
||||||
peg pg(syntax);
|
peg pg(syntax);
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
match m;
|
match m;
|
||||||
while (peg_search(pg, s + pos, l - pos, m)) {
|
while (peg_search(pg, s + pos, n - pos, m)) {
|
||||||
cout << m.str() << endl; // entire match
|
cout << m.str() << endl; // entire match
|
||||||
cout << m.str(1) << endl; // submatch #1
|
cout << m.str(1) << endl; // submatch #1
|
||||||
pos += m.length();
|
pos += m.length();
|
||||||
@ -217,8 +217,8 @@ vector<string> tags;
|
|||||||
|
|
||||||
Definition ROOT, TAG_NAME, _;
|
Definition ROOT, TAG_NAME, _;
|
||||||
ROOT <= seq(_, zom(seq(chr('['), TAG_NAME, chr(']'), _)));
|
ROOT <= seq(_, zom(seq(chr('['), TAG_NAME, chr(']'), _)));
|
||||||
TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const char* s, size_t l) {
|
TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const char* s, size_t n) {
|
||||||
tags.push_back(string(s, l));
|
tags.push_back(string(s, n));
|
||||||
};
|
};
|
||||||
_ <= zom(cls(" \t"));
|
_ <= zom(cls(" \t"));
|
||||||
|
|
||||||
@ -256,10 +256,10 @@ auto syntax = R"(
|
|||||||
|
|
||||||
Rules rules = {
|
Rules rules = {
|
||||||
{
|
{
|
||||||
"NAME", usr([](const char* s, size_t l, SemanticValues& sv, any& c) {
|
"NAME", usr([](const char* s, size_t n, 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() <= n && !n.compare(0, n.size(), s, n.size())) {
|
||||||
return success(n.size());
|
return success(n.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,9 @@ int main(int argc, const char** argv)
|
|||||||
|
|
||||||
parser["EXPRESSION"] = reduce;
|
parser["EXPRESSION"] = reduce;
|
||||||
parser["TERM"] = reduce;
|
parser["TERM"] = reduce;
|
||||||
parser["TERM_OPERATOR"] = [](const char* s, size_t l) { return (char)*s; };
|
parser["TERM_OPERATOR"] = [](const char* s, size_t n) { return (char)*s; };
|
||||||
parser["FACTOR_OPERATOR"] = [](const char* s, size_t l) { return (char)*s; };
|
parser["FACTOR_OPERATOR"] = [](const char* s, size_t n) { return (char)*s; };
|
||||||
parser["NUMBER"] = [](const char* s, size_t l) { return atol(s); };
|
parser["NUMBER"] = [](const char* s, size_t n) { return atol(s); };
|
||||||
|
|
||||||
long val = 0;
|
long val = 0;
|
||||||
if (parser.parse(s, val)) {
|
if (parser.parse(s, val)) {
|
||||||
|
@ -51,12 +51,12 @@ int main(int argc, const char** argv)
|
|||||||
EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))), reduce;
|
EXPRESSION <= seq(TERM, zom(seq(TERM_OPERATOR, TERM))), reduce;
|
||||||
TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))), reduce;
|
TERM <= seq(FACTOR, zom(seq(FACTOR_OPERATOR, FACTOR))), reduce;
|
||||||
FACTOR <= cho(NUMBER, seq(chr('('), EXPRESSION, chr(')')));
|
FACTOR <= cho(NUMBER, seq(chr('('), EXPRESSION, chr(')')));
|
||||||
TERM_OPERATOR <= cls("+-"), [](const char* s, size_t l) { return (char)*s; };
|
TERM_OPERATOR <= cls("+-"), [](const char* s, size_t n) { return (char)*s; };
|
||||||
FACTOR_OPERATOR <= cls("*/"), [](const char* s, size_t l) { return (char)*s; };
|
FACTOR_OPERATOR <= cls("*/"), [](const char* s, size_t n) { return (char)*s; };
|
||||||
NUMBER <= oom(cls("0-9")), [](const char* s, size_t l) { return atol(s); };
|
NUMBER <= oom(cls("0-9")), [](const char* s, size_t n) { return atol(s); };
|
||||||
|
|
||||||
long val = 0;
|
long val = 0;
|
||||||
if (EXPRESSION.parse_with_value(s, val).ret) {
|
if (EXPRESSION.parse_and_get_value(s, val).ret) {
|
||||||
cout << s << " = " << val << endl;
|
cout << s << " = " << val << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ struct ast_num : public ast_node
|
|||||||
|
|
||||||
long eval() override { return num_; };
|
long eval() override { return num_; };
|
||||||
|
|
||||||
static shared_ptr<ast_node> create(const char* s, size_t l) {
|
static shared_ptr<ast_node> create(const char* s, size_t n) {
|
||||||
return make_shared<ast_num>(atol(s));
|
return make_shared<ast_num>(atol(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,12 +112,12 @@ int main(int argc, const char** argv)
|
|||||||
|
|
||||||
parser["EXPRESSION"] = ast_ope::create;
|
parser["EXPRESSION"] = ast_ope::create;
|
||||||
parser["TERM"] = ast_ope::create;
|
parser["TERM"] = ast_ope::create;
|
||||||
parser["TERM_OPERATOR"] = [](const char* s, size_t l) { return *s; };
|
parser["TERM_OPERATOR"] = [](const char* s, size_t n) { return *s; };
|
||||||
parser["FACTOR_OPERATOR"] = [](const char* s, size_t l) { return *s; };
|
parser["FACTOR_OPERATOR"] = [](const char* s, size_t n) { return *s; };
|
||||||
parser["NUMBER"] = ast_num::create;
|
parser["NUMBER"] = ast_num::create;
|
||||||
|
|
||||||
shared_ptr<ast_node> ast;
|
shared_ptr<ast_node> ast;
|
||||||
if (parser.parse_with_value(s, ast)) {
|
if (parser.parse(s, ast)) {
|
||||||
cout << s << " = " << ast->eval() << endl;
|
cout << s << " = " << ast->eval() << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,18 @@ int main(int argc, const char** argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
peglib::peg peg(syntax.data(), syntax.size(), [&](size_t ln, size_t col, const string& msg) {
|
peglib::peg peg;
|
||||||
cerr << syntax_path << ":" << ln << ":" << col << ": " << msg << endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!peg) {
|
bool firstError = true;
|
||||||
|
peg.log = [&](size_t ln, size_t col, const string& msg) {
|
||||||
|
if (firstError) {
|
||||||
|
firstError = false;
|
||||||
|
cerr << "# PEG grammar syntax error" << endl;
|
||||||
|
}
|
||||||
|
cerr << syntax_path << ":" << ln << ":" << col << ": " << msg << endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!peg.load_grammar(syntax.data(), syntax.size())) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,15 +68,20 @@ int main(int argc, const char** argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = peg.parse(source.data(), source.size(), [&](size_t ln, size_t col, const string& msg) {
|
firstError = true;
|
||||||
cerr << source_path << ":" << ln << ":" << col << ": " << msg << endl;
|
peg.log = [&](size_t ln, size_t col, const string& msg) {
|
||||||
});
|
if (firstError) {
|
||||||
|
firstError = false;
|
||||||
|
cerr << "# Source syntax error" << endl;
|
||||||
|
}
|
||||||
|
cerr << syntax_path << ":" << ln << ":" << col << ": " << msg << endl;
|
||||||
|
};
|
||||||
|
|
||||||
if (ret) {
|
if (!peg.parse_n(source.data(), source.size())) {
|
||||||
peg.parse(source.data(), source.size());
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret ? 0 : -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: et ts=4 sw=4 cin cino={1s ff=unix
|
// vim: et ts=4 sw=4 cin cino={1s ff=unix
|
||||||
|
411
peglib.h
411
peglib.h
@ -156,10 +156,10 @@ private:
|
|||||||
*/
|
*/
|
||||||
struct SemanticValue {
|
struct SemanticValue {
|
||||||
SemanticValue()
|
SemanticValue()
|
||||||
: s(nullptr), l(0) {}
|
: s(nullptr), n(0) {}
|
||||||
|
|
||||||
SemanticValue(const any& _val, const char* _name, const char* _s, size_t _l)
|
SemanticValue(const any& _val, const char* _name, const char* _s, size_t _n)
|
||||||
: val(_val), name(_name), s(_s), l(_l) {}
|
: val(_val), name(_name), s(_s), n(_n) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& get() {
|
T& get() {
|
||||||
@ -172,28 +172,28 @@ struct SemanticValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string str() const {
|
std::string str() const {
|
||||||
return std::string(s, l);
|
return std::string(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
any val;
|
any val;
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* s;
|
const char* s;
|
||||||
size_t l;
|
size_t n;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SemanticValues : protected std::vector<SemanticValue>
|
struct SemanticValues : protected std::vector<SemanticValue>
|
||||||
{
|
{
|
||||||
const char* s;
|
const char* s;
|
||||||
size_t l;
|
size_t n;
|
||||||
size_t choice;
|
size_t choice;
|
||||||
|
|
||||||
SemanticValues() : s(nullptr), l(0), choice(0) {}
|
SemanticValues() : s(nullptr), n(0), choice(0) {}
|
||||||
|
|
||||||
std::string str(size_t i = 0) const {
|
std::string str(size_t i = 0) const {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
return (*this)[i].str();
|
return (*this)[i].str();
|
||||||
}
|
}
|
||||||
return std::string(s, l);
|
return std::string(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef SemanticValue T;
|
typedef SemanticValue T;
|
||||||
@ -344,11 +344,11 @@ private:
|
|||||||
|
|
||||||
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 n)> fn) : fn_(fn) {}
|
||||||
any operator()(const SemanticValues& sv, any& dt) {
|
any operator()(const SemanticValues& sv, any& dt) {
|
||||||
return call<R>(fn_, sv.s, sv.l);
|
return call<R>(fn_, sv.s, sv.n);
|
||||||
}
|
}
|
||||||
std::function<R (const char* s, size_t l)> fn_;
|
std::function<R (const char* s, size_t n)> fn_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename R>
|
template <typename R>
|
||||||
@ -428,7 +428,7 @@ private:
|
|||||||
/*
|
/*
|
||||||
* Match action
|
* Match action
|
||||||
*/
|
*/
|
||||||
typedef std::function<void (const char* s, size_t l, size_t id, const std::string& name)> MatchAction;
|
typedef std::function<void (const char* s, size_t n, size_t id, const std::string& name)> MatchAction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Result
|
* Result
|
||||||
@ -512,7 +512,7 @@ struct Context
|
|||||||
sv.clear();
|
sv.clear();
|
||||||
}
|
}
|
||||||
sv.s = nullptr;
|
sv.s = nullptr;
|
||||||
sv.l = 0;
|
sv.n = 0;
|
||||||
return sv;
|
return sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ public:
|
|||||||
struct Visitor;
|
struct Visitor;
|
||||||
|
|
||||||
virtual ~Ope() {};
|
virtual ~Ope() {};
|
||||||
virtual int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const = 0;
|
virtual int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const = 0;
|
||||||
virtual void accept(Visitor& v) = 0;
|
virtual void accept(Visitor& v) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -558,11 +558,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)) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
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 len = rule.parse(s + i, l - i, sv, c, dt);
|
auto len = rule.parse(s + i, n - i, sv, c, dt);
|
||||||
if (fail(len)) {
|
if (fail(len)) {
|
||||||
if (!c.msg) {
|
if (!c.msg) {
|
||||||
c.msg = "missing an element in the 'sequence'";
|
c.msg = "missing an element in the 'sequence'";
|
||||||
@ -602,19 +602,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)) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
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;
|
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
auto len = rule.parse(s, l, chldsv, c, dt);
|
auto len = rule.parse(s, n, chldsv, c, dt);
|
||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
if (!chldsv.empty()) {
|
if (!chldsv.empty()) {
|
||||||
sv.insert(sv.end(), chldsv.begin(), chldsv.end());
|
sv.insert(sv.end(), chldsv.begin(), chldsv.end());
|
||||||
}
|
}
|
||||||
sv.s = chldsv.s;
|
sv.s = chldsv.s;
|
||||||
sv.l = chldsv.l;
|
sv.n = chldsv.n;
|
||||||
sv.choice = id;
|
sv.choice = id;
|
||||||
c.pop();
|
c.pop();
|
||||||
return len;
|
return len;
|
||||||
@ -640,11 +639,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
while (l - i > 0) {
|
while (n - i > 0) {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s + i, l - i, sv, c, dt);
|
auto len = rule.parse(s + i, n - i, sv, c, dt);
|
||||||
if (fail(len)) {
|
if (fail(len)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -664,9 +663,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s, l, sv, c, dt);
|
auto len = rule.parse(s, n, sv, c, dt);
|
||||||
if (fail(len)) {
|
if (fail(len)) {
|
||||||
if (!c.msg) {
|
if (!c.msg) {
|
||||||
c.msg = "nothing occurred in the 'one-or-more'";
|
c.msg = "nothing occurred in the 'one-or-more'";
|
||||||
@ -674,9 +673,9 @@ public:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
auto i = len;
|
auto i = len;
|
||||||
while (l - i > 0) {
|
while (n - i > 0) {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s + i, l - i, sv, c, dt);
|
auto len = rule.parse(s + i, n - i, sv, c, dt);
|
||||||
if (fail(len)) {
|
if (fail(len)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -696,9 +695,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s, l, sv, c, dt);
|
auto len = rule.parse(s, n, sv, c, dt);
|
||||||
return success(len) ? len : 0;
|
return success(len) ? len : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,9 +712,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s, l, sv, c, dt);
|
auto len = rule.parse(s, n, sv, c, dt);
|
||||||
if (success(len)) {
|
if (success(len)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@ -734,9 +733,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s, l, sv, c, dt);
|
auto len = rule.parse(s, n, sv, c, dt);
|
||||||
if (success(len)) {
|
if (success(len)) {
|
||||||
c.error_ptr = s;
|
c.error_ptr = s;
|
||||||
return -1;
|
return -1;
|
||||||
@ -756,10 +755,10 @@ class LiteralString : public Ope
|
|||||||
public:
|
public:
|
||||||
LiteralString(const std::string& s) : lit_(s) {}
|
LiteralString(const std::string& s) : lit_(s) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
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 >= n || s[i] != lit_[i]) {
|
||||||
c.error_ptr = s;
|
c.error_ptr = s;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -778,9 +777,9 @@ class CharacterClass : public Ope
|
|||||||
public:
|
public:
|
||||||
CharacterClass(const std::string& chars) : chars_(chars) {}
|
CharacterClass(const std::string& chars) : chars_(chars) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
// TODO: UTF8 support
|
// TODO: UTF8 support
|
||||||
if (l < 1) {
|
if (n < 1) {
|
||||||
c.error_ptr = s;
|
c.error_ptr = s;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -814,9 +813,9 @@ class Character : public Ope
|
|||||||
public:
|
public:
|
||||||
Character(char ch) : ch_(ch) {}
|
Character(char ch) : ch_(ch) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
// TODO: UTF8 support
|
// TODO: UTF8 support
|
||||||
if (l < 1 || s[0] != ch_) {
|
if (n < 1 || s[0] != ch_) {
|
||||||
c.error_ptr = s;
|
c.error_ptr = s;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -832,9 +831,9 @@ public:
|
|||||||
class AnyCharacter : public Ope
|
class AnyCharacter : public Ope
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
// TODO: UTF8 support
|
// TODO: UTF8 support
|
||||||
if (l < 1) {
|
if (n < 1) {
|
||||||
c.error_ptr = s;
|
c.error_ptr = s;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -850,10 +849,10 @@ public:
|
|||||||
Capture(const std::shared_ptr<Ope>& ope, MatchAction ma, size_t n, const std::string& s)
|
Capture(const std::shared_ptr<Ope>& ope, MatchAction ma, size_t n, const std::string& s)
|
||||||
: ope_(ope), match_action_(ma), id(n), name(s) {}
|
: ope_(ope), match_action_(ma), id(n), name(s) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
assert(ope_);
|
assert(ope_);
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s, l, sv, c, dt);
|
auto len = rule.parse(s, n, sv, c, dt);
|
||||||
if (success(len) && match_action_) {
|
if (success(len) && match_action_) {
|
||||||
match_action_(s, len, id, name);
|
match_action_(s, len, id, name);
|
||||||
}
|
}
|
||||||
@ -874,13 +873,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
assert(ope_);
|
assert(ope_);
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
auto len = rule.parse(s, l, sv, c, dt);
|
auto len = rule.parse(s, n, sv, c, dt);
|
||||||
if (success(len)) {
|
if (success(len)) {
|
||||||
sv.s = s;
|
sv.s = s;
|
||||||
sv.l = len;
|
sv.n = len;
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -891,22 +890,22 @@ public:
|
|||||||
std::shared_ptr<Ope> ope_;
|
std::shared_ptr<Ope> ope_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<int (const char* s, size_t l, SemanticValues& sv, any& dt)> Parser;
|
typedef std::function<int (const char* s, size_t n, 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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
assert(fn_);
|
assert(fn_);
|
||||||
return fn_(s, l, sv, dt);
|
return fn_(s, n, sv, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
//private:
|
//private:
|
||||||
std::function<int (const char* s, size_t l, SemanticValues& sv, any& dt)> fn_;
|
std::function<int (const char* s, size_t n, SemanticValues& sv, any& dt)> fn_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WeakHolder : public Ope
|
class WeakHolder : public Ope
|
||||||
@ -914,11 +913,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) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override {
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||||
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, sv, c, dt);
|
return rule.parse(s, n, sv, c, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
@ -935,7 +934,7 @@ public:
|
|||||||
Holder(Definition* outer)
|
Holder(Definition* outer)
|
||||||
: outer_(outer) {}
|
: outer_(outer) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override;
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
@ -956,7 +955,7 @@ public:
|
|||||||
: grammar_(grammar)
|
: grammar_(grammar)
|
||||||
, name_(name) {}
|
, name_(name) {}
|
||||||
|
|
||||||
int parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const override;
|
int parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override;
|
||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
@ -1104,32 +1103,32 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result parse(const char* s, size_t l) const {
|
Result parse(const char* s, size_t n) const {
|
||||||
SemanticValues sv;
|
SemanticValues sv;
|
||||||
any dt;
|
any dt;
|
||||||
return parse_core(s, l, sv, dt);
|
return parse_core(s, n, sv, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result parse(const char* s) const {
|
Result parse(const char* s) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return parse(s, l);
|
return parse(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result parse_with_data(const char* s, size_t l, any& dt) const {
|
Result parse(const char* s, size_t n, any& dt) const {
|
||||||
SemanticValues sv;
|
SemanticValues sv;
|
||||||
return parse_core(s, l, sv, dt);
|
return parse_core(s, n, sv, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result parse_with_data(const char* s, any& dt) const {
|
Result parse(const char* s, any& dt) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return parse_with_data(s, l, dt);
|
return parse(s, n, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Result parse_with_value(const char* s, size_t l, T& val) const {
|
Result parse_and_get_value(const char* s, size_t n, T& val) const {
|
||||||
SemanticValues sv;
|
SemanticValues sv;
|
||||||
any dt;
|
any dt;
|
||||||
auto r = parse_core(s, l, sv, dt);
|
auto r = parse_core(s, n, sv, dt);
|
||||||
if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) {
|
if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) {
|
||||||
val = sv[0].val.get<T>();
|
val = sv[0].val.get<T>();
|
||||||
}
|
}
|
||||||
@ -1137,9 +1136,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Result parse_with_value(const char* s, T& val) const {
|
Result parse_and_get_value(const char* s, T& val) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return parse_with_value(s, l, val);
|
return parse_and_get_value(s, n, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Result parse_and_get_value(const char* s, size_t n, any& dt, T& val) const {
|
||||||
|
SemanticValues sv;
|
||||||
|
auto r = parse_core(s, n, sv, dt);
|
||||||
|
if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) {
|
||||||
|
val = sv[0].val.get<T>();
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Result parse_and_get_value(const char* s, any& dt, T& val) const {
|
||||||
|
auto n = strlen(s);
|
||||||
|
return parse_and_get_value(s, n, dt, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Definition& operator=(Action ac) {
|
Definition& operator=(Action ac) {
|
||||||
@ -1180,12 +1195,12 @@ private:
|
|||||||
Definition& operator=(const Definition& rhs);
|
Definition& operator=(const Definition& rhs);
|
||||||
Definition& operator=(Definition&& rhs);
|
Definition& operator=(Definition&& rhs);
|
||||||
|
|
||||||
Result parse_core(const char* s, size_t l, SemanticValues& sv, any& dt) const {
|
Result parse_core(const char* s, size_t n, SemanticValues& sv, any& dt) const {
|
||||||
DefinitionIDs defIds;
|
DefinitionIDs defIds;
|
||||||
holder_->accept(defIds);
|
holder_->accept(defIds);
|
||||||
|
|
||||||
Context c(s, l, defIds.ids.size(), enablePackratParsing);
|
Context c(s, n, defIds.ids.size(), enablePackratParsing);
|
||||||
auto len = holder_->parse(s, l, sv, c, dt);
|
auto len = holder_->parse(s, n, sv, c, dt);
|
||||||
return Result { success(len), len, c.error_ptr, c.msg };
|
return Result { success(len), len, c.error_ptr, c.msg };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,7 +1213,7 @@ typedef Definition rule;
|
|||||||
* Implementations
|
* Implementations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline int Holder::parse(const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const {
|
inline int Holder::parse(const char* s, size_t n, SemanticValues& sv, Context& c, 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...");
|
||||||
}
|
}
|
||||||
@ -1206,14 +1221,14 @@ inline int Holder::parse(const char* s, size_t l, SemanticValues& sv, Context& c
|
|||||||
int len;
|
int len;
|
||||||
any val;
|
any val;
|
||||||
const char* ancs = s;
|
const char* ancs = s;
|
||||||
size_t ancl = l;
|
size_t ancn = n;
|
||||||
|
|
||||||
c.packrat(s, outer_->id, len, val, [&](int& len, any& val) {
|
c.packrat(s, outer_->id, len, val, [&](int& len, any& val) {
|
||||||
auto& chldsv = c.push();
|
auto& chldsv = c.push();
|
||||||
|
|
||||||
const auto& rule = *ope_;
|
const auto& rule = *ope_;
|
||||||
len = rule.parse(s, l, chldsv, c, dt);
|
len = rule.parse(s, n, chldsv, c, dt);
|
||||||
ancl = len;
|
ancn = len;
|
||||||
if (success(len) && !outer_->ignoreSemanticValue) {
|
if (success(len) && !outer_->ignoreSemanticValue) {
|
||||||
assert(!outer_->actions.empty());
|
assert(!outer_->actions.empty());
|
||||||
|
|
||||||
@ -1224,10 +1239,10 @@ inline int Holder::parse(const char* s, size_t l, SemanticValues& sv, Context& c
|
|||||||
|
|
||||||
if (chldsv.s) {
|
if (chldsv.s) {
|
||||||
ancs = chldsv.s;
|
ancs = chldsv.s;
|
||||||
ancl = chldsv.l;
|
ancn = chldsv.n;
|
||||||
} else {
|
} else {
|
||||||
chldsv.s = s;
|
chldsv.s = s;
|
||||||
chldsv.l = len;
|
chldsv.n = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = reduce(chldsv, dt, action);
|
val = reduce(chldsv, dt, action);
|
||||||
@ -1237,7 +1252,7 @@ inline int Holder::parse(const char* s, size_t l, SemanticValues& sv, Context& c
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (success(len) && !outer_->ignoreSemanticValue) {
|
if (success(len) && !outer_->ignoreSemanticValue) {
|
||||||
sv.emplace_back(val, outer_->name.c_str(), ancs, ancl);
|
sv.emplace_back(val, outer_->name.c_str(), ancs, ancn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@ -1254,9 +1269,9 @@ inline any Holder::reduce(const SemanticValues& sv, any& dt, const Action& actio
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline int DefinitionReference::parse(
|
inline int DefinitionReference::parse(
|
||||||
const char* s, size_t l, SemanticValues& sv, Context& c, any& dt) const {
|
const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const {
|
||||||
const auto& rule = *get_rule();
|
const auto& rule = *get_rule();
|
||||||
return rule.parse(s, l, sv, c, dt);
|
return rule.parse(s, n, sv, c, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::shared_ptr<Ope> DefinitionReference::get_rule() const {
|
inline std::shared_ptr<Ope> DefinitionReference::get_rule() const {
|
||||||
@ -1359,7 +1374,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<int (const char* s, size_t l, SemanticValues& sv, any& dt)> fn) {
|
inline std::shared_ptr<Ope> usr(std::function<int (const char* s, size_t n, SemanticValues& sv, any& dt)> fn) {
|
||||||
return std::make_shared<User>(fn);
|
return std::make_shared<User>(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1399,25 +1414,25 @@ class PEGParser
|
|||||||
public:
|
public:
|
||||||
static std::shared_ptr<Grammar> parse(
|
static std::shared_ptr<Grammar> parse(
|
||||||
const char* s,
|
const char* s,
|
||||||
size_t l,
|
size_t n,
|
||||||
const Rules& rules,
|
const Rules& rules,
|
||||||
std::string& start,
|
std::string& start,
|
||||||
MatchAction ma,
|
MatchAction ma,
|
||||||
Log log)
|
Log log)
|
||||||
{
|
{
|
||||||
static PEGParser instance;
|
static PEGParser instance;
|
||||||
return get().perform_core(s, l, rules, start, ma, log);
|
return get().perform_core(s, n, rules, start, ma, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Grammar> parse(
|
static std::shared_ptr<Grammar> parse(
|
||||||
const char* s,
|
const char* s,
|
||||||
size_t l,
|
size_t n,
|
||||||
std::string& start,
|
std::string& start,
|
||||||
MatchAction ma,
|
MatchAction ma,
|
||||||
Log log)
|
Log log)
|
||||||
{
|
{
|
||||||
Rules dummy;
|
Rules dummy;
|
||||||
return parse(s, l, dummy, start, ma, log);
|
return parse(s, n, dummy, start, ma, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For debuging purpose
|
// For debuging purpose
|
||||||
@ -1555,7 +1570,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
g["Prefix"] = [&](const SemanticValues& sv, any& dt) {
|
g["Prefix"] = [&](const SemanticValues& sv) {
|
||||||
std::shared_ptr<Ope> ope;
|
std::shared_ptr<Ope> ope;
|
||||||
if (sv.size() == 1) {
|
if (sv.size() == 1) {
|
||||||
ope = sv[0].val.get<std::shared_ptr<Ope>>();
|
ope = sv[0].val.get<std::shared_ptr<Ope>>();
|
||||||
@ -1572,7 +1587,7 @@ private:
|
|||||||
return ope;
|
return ope;
|
||||||
};
|
};
|
||||||
|
|
||||||
g["Suffix"] = [&](const SemanticValues& sv, any& dt) {
|
g["Suffix"] = [&](const SemanticValues& sv) {
|
||||||
auto ope = sv[0].val.get<std::shared_ptr<Ope>>();
|
auto ope = sv[0].val.get<std::shared_ptr<Ope>>();
|
||||||
if (sv.size() == 1) {
|
if (sv.size() == 1) {
|
||||||
return ope;
|
return ope;
|
||||||
@ -1610,34 +1625,34 @@ private:
|
|||||||
// Capture
|
// Capture
|
||||||
[&](const SemanticValues& sv, any& dt) {
|
[&](const SemanticValues& sv, any& dt) {
|
||||||
Data& data = *dt.get<Data*>();
|
Data& data = *dt.get<Data*>();
|
||||||
auto name = std::string(sv[0].s, sv[0].l);
|
auto name = std::string(sv[0].s, sv[0].n);
|
||||||
auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
|
auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
|
||||||
return cap(ope, data.match_action, ++data.capture_count, name);
|
return cap(ope, data.match_action, ++data.capture_count, name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
g["IdentCont"] = [](const char* s, size_t l) {
|
g["IdentCont"] = [](const char* s, size_t n) {
|
||||||
return std::string(s, l);
|
return std::string(s, n);
|
||||||
};
|
};
|
||||||
g["Literal"] = [this](const char* s, size_t l) {
|
g["Literal"] = [this](const char* s, size_t n) {
|
||||||
return lit(resolve_escape_sequence(s, l));
|
return lit(resolve_escape_sequence(s, n));
|
||||||
};
|
};
|
||||||
g["Class"] = [this](const char* s, size_t l) {
|
g["Class"] = [this](const char* s, size_t n) {
|
||||||
return cls(resolve_escape_sequence(s, l));
|
return cls(resolve_escape_sequence(s, n));
|
||||||
};
|
};
|
||||||
|
|
||||||
g["AND"] = [](const char* s, size_t l) { return *s; };
|
g["AND"] = [](const char* s, size_t n) { return *s; };
|
||||||
g["NOT"] = [](const char* s, size_t l) { return *s; };
|
g["NOT"] = [](const char* s, size_t n) { return *s; };
|
||||||
g["QUESTION"] = [](const char* s, size_t l) { return *s; };
|
g["QUESTION"] = [](const char* s, size_t n) { return *s; };
|
||||||
g["STAR"] = [](const char* s, size_t l) { return *s; };
|
g["STAR"] = [](const char* s, size_t n) { return *s; };
|
||||||
g["PLUS"] = [](const char* s, size_t l) { return *s; };
|
g["PLUS"] = [](const char* s, size_t n) { return *s; };
|
||||||
|
|
||||||
g["DOT"] = []() { return dot(); };
|
g["DOT"] = []() { return dot(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Grammar> perform_core(
|
std::shared_ptr<Grammar> perform_core(
|
||||||
const char* s,
|
const char* s,
|
||||||
size_t l,
|
size_t n,
|
||||||
const Rules& rules,
|
const Rules& rules,
|
||||||
std::string& start,
|
std::string& start,
|
||||||
MatchAction ma,
|
MatchAction ma,
|
||||||
@ -1647,7 +1662,7 @@ private:
|
|||||||
data.match_action = ma;
|
data.match_action = ma;
|
||||||
|
|
||||||
any dt = &data;
|
any dt = &data;
|
||||||
auto r = g["Grammar"].parse_with_data(s, l, dt);
|
auto r = g["Grammar"].parse(s, n, dt);
|
||||||
|
|
||||||
if (!r.ret) {
|
if (!r.ret) {
|
||||||
if (log) {
|
if (log) {
|
||||||
@ -1717,29 +1732,29 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<char, int> parse_hex_number(const char* s, size_t l, size_t i) {
|
std::pair<char, int> parse_hex_number(const char* s, size_t n, size_t i) {
|
||||||
char ret = 0;
|
char ret = 0;
|
||||||
int n;
|
int val;
|
||||||
if (i < l && is_hex(s[i], n)) {
|
if (i < n && is_hex(s[i], val)) {
|
||||||
ret = n;
|
ret = n;
|
||||||
if (i + 1 < l && is_hex(s[i + 1], n)) {
|
if (i + 1 < n && is_hex(s[i + 1], val)) {
|
||||||
ret = ret * 16 + n;
|
ret = ret * 16 + val;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::make_pair(ret, i);
|
return std::make_pair(ret, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<char, int> parse_octal_number(const char* s, size_t l, size_t i) {
|
std::pair<char, int> parse_octal_number(const char* s, size_t n, size_t i) {
|
||||||
char ret = 0;
|
char ret = 0;
|
||||||
int n;
|
int val;
|
||||||
if (i < l && is_digit(s[i], n)) {
|
if (i < n && is_digit(s[i], val)) {
|
||||||
ret = n;
|
ret = n;
|
||||||
if (i + 1 < l && is_digit(s[i + 1], n)) {
|
if (i + 1 < n && is_digit(s[i + 1], val)) {
|
||||||
ret = ret * 8 + n;
|
ret = ret * 8 + val;
|
||||||
i++;
|
i++;
|
||||||
if (i + 1 < l && is_digit(s[i + 1], n)) {
|
if (i + 1 < n && is_digit(s[i + 1], val)) {
|
||||||
ret = ret * 8 + n;
|
ret = ret * 8 + val;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1747,11 +1762,11 @@ private:
|
|||||||
return std::make_pair(ret, i);
|
return std::make_pair(ret, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string resolve_escape_sequence(const char* s, size_t l) {
|
std::string resolve_escape_sequence(const char* s, size_t n) {
|
||||||
std::string r;
|
std::string r;
|
||||||
r.reserve(l);
|
r.reserve(n);
|
||||||
|
|
||||||
for (auto i = 0u; i < l; i++) {
|
for (auto i = 0u; i < n; i++) {
|
||||||
auto ch = s[i];
|
auto ch = s[i];
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
i++;
|
i++;
|
||||||
@ -1765,12 +1780,12 @@ private:
|
|||||||
case ']': r += ']'; break;
|
case ']': r += ']'; break;
|
||||||
case '\\': r += '\\'; break;
|
case '\\': r += '\\'; break;
|
||||||
case 'x': {
|
case 'x': {
|
||||||
std::tie(ch, i) = parse_hex_number(s, l, i + 1);
|
std::tie(ch, i) = parse_hex_number(s, n, i + 1);
|
||||||
r += ch;
|
r += ch;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
std::tie(ch, i) = parse_octal_number(s, l, i + 1);
|
std::tie(ch, i) = parse_octal_number(s, n, i + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1793,82 +1808,119 @@ class peg
|
|||||||
public:
|
public:
|
||||||
peg() = default;
|
peg() = default;
|
||||||
|
|
||||||
peg(const char* s, size_t l, const Rules& rules, Log log = nullptr) {
|
peg(const char* s, size_t n, const Rules& rules) {
|
||||||
grammar_ = PEGParser::parse(
|
load_grammar(s, n, rules);
|
||||||
s, l, rules,
|
|
||||||
start_,
|
|
||||||
[&](const char* s, size_t l, size_t id, const std::string& name) {
|
|
||||||
if (match_action) match_action(s, l, id, name);
|
|
||||||
},
|
|
||||||
log);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
peg(const char* s, const Rules& rules, Log log = nullptr)
|
peg(const char* s, const Rules& rules)
|
||||||
: peg(s, strlen(s), rules, log) {}
|
: peg(s, strlen(s), rules) {}
|
||||||
|
|
||||||
peg(const char* s, size_t l, Log log = nullptr)
|
peg(const char* s, size_t n)
|
||||||
: peg(s, l, Rules(), log) {}
|
: peg(s, n, Rules()) {}
|
||||||
|
|
||||||
peg(const char* s, Log log = nullptr)
|
peg(const char* s)
|
||||||
: peg(s, strlen(s), Rules(), log) {}
|
: peg(s, strlen(s), Rules()) {}
|
||||||
|
|
||||||
operator bool() {
|
operator bool() {
|
||||||
return grammar_ != nullptr;
|
return grammar_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse(const char* s, size_t l, Log log = nullptr) const {
|
bool load_grammar(const char* s, size_t n, const Rules& rules) {
|
||||||
|
grammar_ = PEGParser::parse(
|
||||||
|
s, n, rules,
|
||||||
|
start_,
|
||||||
|
[&](const char* s, size_t n, size_t id, const std::string& name) {
|
||||||
|
if (match_action) match_action(s, n, id, name);
|
||||||
|
},
|
||||||
|
log);
|
||||||
|
|
||||||
|
return grammar_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_grammar(const char* s, size_t n) {
|
||||||
|
return load_grammar(s, n, Rules());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_grammar(const char* s, const Rules& rules) {
|
||||||
|
auto n = strlen(s);
|
||||||
|
return load_grammar(s, n, rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_grammar(const char* s) {
|
||||||
|
auto n = strlen(s);
|
||||||
|
return load_grammar(s, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_n(const char* s, size_t n) const {
|
||||||
if (grammar_ != nullptr) {
|
if (grammar_ != nullptr) {
|
||||||
const auto& rule = (*grammar_)[start_];
|
const auto& rule = (*grammar_)[start_];
|
||||||
auto r = rule.parse(s, l);
|
auto r = rule.parse(s, n);
|
||||||
output_log(s, l, log, r);
|
output_log(s, n, log, r);
|
||||||
return r.ret && r.len == l;
|
return r.ret && r.len == n;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse(const char* s, Log log = nullptr) const {
|
bool parse(const char* s) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return parse(s, l, log);
|
return parse_n(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_with_data(const char* s, size_t l, any& dt, Log log = nullptr) const {
|
bool parse_n(const char* s, size_t n, any& dt) const {
|
||||||
if (grammar_ != nullptr) {
|
if (grammar_ != nullptr) {
|
||||||
const auto& rule = (*grammar_)[start_];
|
const auto& rule = (*grammar_)[start_];
|
||||||
auto r = rule.parse_with_data(s, l, dt);
|
auto r = rule.parse(s, n, dt);
|
||||||
output_log(s, l, log, r);
|
output_log(s, n, log, r);
|
||||||
return r.ret && r.len == l;
|
return r.ret && r.len == n;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_with_data(const char* s, any& dt, Log log = nullptr) const {
|
bool parse(const char* s, any& dt) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return parse_with_data(s, l, dt, log);
|
return parse_n(s, n, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool parse_with_value(const char* s, size_t l, T& out, Log log = nullptr) const {
|
bool parse_n(const char* s, size_t n, T& val) const {
|
||||||
if (grammar_ != nullptr) {
|
if (grammar_ != nullptr) {
|
||||||
const auto& rule = (*grammar_)[start_];
|
const auto& rule = (*grammar_)[start_];
|
||||||
auto r = rule.parse_with_value(s, l, out);
|
auto r = rule.parse_and_get_value(s, n, val);
|
||||||
output_log(s, l, log, r);
|
output_log(s, n, log, r);
|
||||||
return r.ret && r.len == l;
|
return r.ret && r.len == n;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool parse_with_value(const char* s, T& out, Log log = nullptr) const {
|
bool parse(const char* s, T& val) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return parse_with_value(s, l, out, log);
|
return parse_n(s, n, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool search(const char* s, size_t l, size_t& mpos, size_t& mlen) const {
|
template <typename T>
|
||||||
|
bool parse_n(const char* s, size_t n, any& dt, T& val) const {
|
||||||
|
if (grammar_ != nullptr) {
|
||||||
|
const auto& rule = (*grammar_)[start_];
|
||||||
|
auto r = rule.parse_and_get_value(s, n, dt, val);
|
||||||
|
output_log(s, n, log, r);
|
||||||
|
return r.ret && r.len == n;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool parse(const char* s, any& dt, T& val) const {
|
||||||
|
auto n = strlen(s);
|
||||||
|
return parse_n(s, n, dt, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search(const char* s, size_t n, size_t& mpos, size_t& mlen) const {
|
||||||
const auto& rule = (*grammar_)[start_];
|
const auto& rule = (*grammar_)[start_];
|
||||||
if (grammar_ != nullptr) {
|
if (grammar_ != nullptr) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while (pos < l) {
|
while (pos < n) {
|
||||||
size_t len = l - pos;
|
size_t len = n - pos;
|
||||||
auto r = rule.parse(s + pos, len);
|
auto r = rule.parse(s + pos, len);
|
||||||
if (r.ret) {
|
if (r.ret) {
|
||||||
mpos = pos;
|
mpos = pos;
|
||||||
@ -1884,8 +1936,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool search(const char* s, size_t& mpos, size_t& mlen) const {
|
bool search(const char* s, size_t& mpos, size_t& mlen) const {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return search(s, l, mpos, mlen);
|
return search(s, n, mpos, mlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
Definition& operator[](const char* s) {
|
Definition& operator[](const char* s) {
|
||||||
@ -1900,14 +1952,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
MatchAction match_action;
|
MatchAction match_action;
|
||||||
|
Log log;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void output_log(const char* s, size_t l, Log log, const Definition::Result& r) const {
|
void output_log(const char* s, size_t n, Log log, const Definition::Result& r) const {
|
||||||
if (log) {
|
if (log) {
|
||||||
if (!r.ret) {
|
if (!r.ret) {
|
||||||
auto line = line_info(s, r.error_ptr);
|
auto line = line_info(s, r.error_ptr);
|
||||||
log(line.first, line.second, r.msg ? "syntax error" : r.msg);
|
log(line.first, line.second, r.msg ? "syntax error" : r.msg);
|
||||||
} else if (r.len != l) {
|
} else if (r.len != n) {
|
||||||
auto line = line_info(s, s + r.len);
|
auto line = line_info(s, s + r.len);
|
||||||
log(line.first, line.second, "syntax error");
|
log(line.first, line.second, "syntax error");
|
||||||
}
|
}
|
||||||
@ -1926,12 +1979,12 @@ struct match
|
|||||||
{
|
{
|
||||||
struct Item {
|
struct Item {
|
||||||
const char* s;
|
const char* s;
|
||||||
size_t l;
|
size_t n;
|
||||||
size_t id;
|
size_t id;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
size_t length() const { return l; }
|
size_t length() const { return n; }
|
||||||
std::string str() const { return std::string(s, l); }
|
std::string str() const { return std::string(s, n); }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Item> matches;
|
std::vector<Item> matches;
|
||||||
@ -2016,14 +2069,14 @@ inline bool peg_match(const char* syntax, const char* s, match& m) {
|
|||||||
m.matches.clear();
|
m.matches.clear();
|
||||||
|
|
||||||
peg pg(syntax);
|
peg pg(syntax);
|
||||||
pg.match_action = [&](const char* s, size_t l, size_t id, const std::string& name) {
|
pg.match_action = [&](const char* s, size_t n, size_t id, const std::string& name) {
|
||||||
m.matches.push_back(match::Item{ s, l, id, name });
|
m.matches.push_back(match::Item{ s, n, id, name });
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ret = pg.parse(s);
|
auto ret = pg.parse(s);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
m.matches.insert(m.matches.begin(), match::Item{ s, l, 0, std::string() });
|
m.matches.insert(m.matches.begin(), match::Item{ s, n, 0, std::string() });
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -2034,15 +2087,15 @@ inline bool peg_match(const char* syntax, const char* s) {
|
|||||||
return pg.parse(s);
|
return pg.parse(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool peg_search(peg& pg, const char* s, size_t l, match& m) {
|
inline bool peg_search(peg& pg, const char* s, size_t n, match& m) {
|
||||||
m.matches.clear();
|
m.matches.clear();
|
||||||
|
|
||||||
pg.match_action = [&](const char* s, size_t l, size_t id, const std::string& name) {
|
pg.match_action = [&](const char* s, size_t n, size_t id, const std::string& name) {
|
||||||
m.matches.push_back(match::Item{ s, l, id, name });
|
m.matches.push_back(match::Item{ s, n, id, name });
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t mpos, mlen;
|
size_t mpos, mlen;
|
||||||
auto ret = pg.search(s, l, mpos, mlen);
|
auto ret = pg.search(s, n, mpos, mlen);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
m.matches.insert(m.matches.begin(), match::Item{ s + mpos, mlen, 0, std::string() });
|
m.matches.insert(m.matches.begin(), match::Item{ s + mpos, mlen, 0, std::string() });
|
||||||
return true;
|
return true;
|
||||||
@ -2052,19 +2105,19 @@ inline bool peg_search(peg& pg, const char* s, size_t l, match& m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool peg_search(peg& pg, const char* s, match& m) {
|
inline bool peg_search(peg& pg, const char* s, match& m) {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return peg_search(pg, s, l, m);
|
return peg_search(pg, s, n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool peg_search(const char* syntax, const char* s, size_t l, match& m) {
|
inline bool peg_search(const char* syntax, const char* s, size_t n, match& m) {
|
||||||
peg pg(syntax);
|
peg pg(syntax);
|
||||||
return peg_search(pg, s, l, m);
|
return peg_search(pg, s, n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool peg_search(const char* syntax, const char* s, match& m) {
|
inline bool peg_search(const char* syntax, const char* s, match& m) {
|
||||||
peg pg(syntax);
|
peg pg(syntax);
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
return peg_search(pg, s, l, m);
|
return peg_search(pg, s, n, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
class peg_token_iterator : public std::iterator<std::forward_iterator_tag, match>
|
class peg_token_iterator : public std::iterator<std::forward_iterator_tag, match>
|
||||||
@ -2080,8 +2133,8 @@ public:
|
|||||||
, s_(s)
|
, s_(s)
|
||||||
, l_(strlen(s))
|
, l_(strlen(s))
|
||||||
, pos_(0) {
|
, pos_(0) {
|
||||||
peg_.match_action = [&](const char* s, size_t l, size_t id, const std::string& name) {
|
peg_.match_action = [&](const char* s, size_t n, size_t id, const std::string& name) {
|
||||||
m_.matches.push_back(match::Item{ s, l, id, name });
|
m_.matches.push_back(match::Item{ s, n, id, name });
|
||||||
};
|
};
|
||||||
search();
|
search();
|
||||||
}
|
}
|
||||||
|
56
test/test.cc
56
test/test.cc
@ -33,8 +33,8 @@ TEST_CASE("String capture test", "[general]")
|
|||||||
|
|
||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags;
|
||||||
|
|
||||||
parser["TAG_NAME"] = [&](const char* s, size_t l) {
|
parser["TAG_NAME"] = [&](const char* s, size_t n) {
|
||||||
tags.push_back(std::string(s, l));
|
tags.push_back(std::string(s, n));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ret = parser.parse(" [tag1] [tag:2] [tag-3] ");
|
auto ret = parser.parse(" [tag1] [tag:2] [tag-3] ");
|
||||||
@ -73,7 +73,7 @@ TEST_CASE("String capture test2", "[general]")
|
|||||||
rule ROOT, TAG, TAG_NAME, WS;
|
rule ROOT, TAG, TAG_NAME, WS;
|
||||||
ROOT <= seq(WS, zom(TAG));
|
ROOT <= seq(WS, zom(TAG));
|
||||||
TAG <= seq(chr('['), TAG_NAME, chr(']'), WS);
|
TAG <= seq(chr('['), TAG_NAME, chr(']'), WS);
|
||||||
TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const char* s, size_t l) { tags.push_back(string(s, l)); };
|
TAG_NAME <= oom(seq(npd(chr(']')), dot())), [&](const char* s, size_t n) { tags.push_back(string(s, n)); };
|
||||||
WS <= zom(cls(" \t"));
|
WS <= zom(cls(" \t"));
|
||||||
|
|
||||||
auto r = ROOT.parse(" [tag1] [tag:2] [tag-3] ");
|
auto r = ROOT.parse(" [tag1] [tag:2] [tag-3] ");
|
||||||
@ -97,8 +97,8 @@ TEST_CASE("String capture test3", "[general]")
|
|||||||
|
|
||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags;
|
||||||
|
|
||||||
pg["TOKEN"] = [&](const char* s, size_t l) {
|
pg["TOKEN"] = [&](const char* s, size_t n) {
|
||||||
tags.push_back(std::string(s, l));
|
tags.push_back(std::string(s, n));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ret = pg.parse(" [tag1] [tag:2] [tag-3] ");
|
auto ret = pg.parse(" [tag1] [tag:2] [tag-3] ");
|
||||||
@ -137,8 +137,8 @@ TEST_CASE("String capture test with embedded match action", "[general]")
|
|||||||
|
|
||||||
ROOT <= seq(WS, zom(TAG));
|
ROOT <= seq(WS, zom(TAG));
|
||||||
TAG <= seq(chr('['),
|
TAG <= seq(chr('['),
|
||||||
cap(TAG_NAME, [&](const char* s, size_t l, size_t id, const std::string& name) {
|
cap(TAG_NAME, [&](const char* s, size_t n, size_t id, const std::string& name) {
|
||||||
tags.push_back(string(s, l));
|
tags.push_back(string(s, n));
|
||||||
}),
|
}),
|
||||||
chr(']'),
|
chr(']'),
|
||||||
WS);
|
WS);
|
||||||
@ -185,7 +185,7 @@ TEST_CASE("Lambda action test", "[general]")
|
|||||||
" CHAR <- . ");
|
" CHAR <- . ");
|
||||||
|
|
||||||
string ss;
|
string ss;
|
||||||
parser["CHAR"] = [&](const char* s, size_t l) {
|
parser["CHAR"] = [&](const char* s, size_t n) {
|
||||||
ss += *s;
|
ss += *s;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ TEST_CASE("Backtracking test", "[general]")
|
|||||||
);
|
);
|
||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
parser["HELLO"] = [&](const char* s, size_t l) {
|
parser["HELLO"] = [&](const char* s, size_t n) {
|
||||||
count++;
|
count++;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,8 +250,8 @@ TEST_CASE("mutable lambda test", "[general]")
|
|||||||
peg pg("ROOT <- 'mutable lambda test'");
|
peg pg("ROOT <- 'mutable lambda test'");
|
||||||
|
|
||||||
// This test makes sure if the following code can be compiled.
|
// This test makes sure if the following code can be compiled.
|
||||||
pg["TOKEN"] = [=](const char* s, size_t l) mutable {
|
pg["TOKEN"] = [=](const char* s, size_t n) mutable {
|
||||||
vec.push_back(string(s, l));
|
vec.push_back(string(s, n));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,12 +283,12 @@ TEST_CASE("Simple calculator test", "[general]")
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser["Number"] = [](const char* s, size_t l) {
|
parser["Number"] = [](const char* s, size_t n) {
|
||||||
return atoi(s);
|
return atoi(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
int val;
|
int val;
|
||||||
parser.parse_with_value("(1+2)*3", val);
|
parser.parse("(1+2)*3", val);
|
||||||
|
|
||||||
REQUIRE(val == 9);
|
REQUIRE(val == 9);
|
||||||
}
|
}
|
||||||
@ -322,13 +322,13 @@ TEST_CASE("Calculator test", "[general]")
|
|||||||
|
|
||||||
EXPRESSION = reduce;
|
EXPRESSION = reduce;
|
||||||
TERM = reduce;
|
TERM = reduce;
|
||||||
TERM_OPERATOR = [](const char* s, size_t l) { return *s; };
|
TERM_OPERATOR = [](const char* s, size_t n) { return *s; };
|
||||||
FACTOR_OPERATOR = [](const char* s, size_t l) { return *s; };
|
FACTOR_OPERATOR = [](const char* s, size_t n) { return *s; };
|
||||||
NUMBER = [&](const char* s, size_t l) { return stol(string(s, l), nullptr, 10); };
|
NUMBER = [&](const char* s, size_t n) { return stol(string(s, n), nullptr, 10); };
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
long val;
|
long val;
|
||||||
auto r = EXPRESSION.parse_with_value("1+2*3*(4-5+6)/7-8", val);
|
auto r = EXPRESSION.parse_and_get_value("1+2*3*(4-5+6)/7-8", val);
|
||||||
|
|
||||||
REQUIRE(r.ret == true);
|
REQUIRE(r.ret == true);
|
||||||
REQUIRE(val == -3);
|
REQUIRE(val == -3);
|
||||||
@ -368,13 +368,13 @@ TEST_CASE("Calculator test2", "[general]")
|
|||||||
|
|
||||||
g["EXPRESSION"] = reduce;
|
g["EXPRESSION"] = reduce;
|
||||||
g["TERM"] = reduce;
|
g["TERM"] = reduce;
|
||||||
g["TERM_OPERATOR"] = [](const char* s, size_t l) { return *s; };
|
g["TERM_OPERATOR"] = [](const char* s, size_t n) { return *s; };
|
||||||
g["FACTOR_OPERATOR"] = [](const char* s, size_t l) { return *s; };
|
g["FACTOR_OPERATOR"] = [](const char* s, size_t n) { return *s; };
|
||||||
g["NUMBER"] = [](const char* s, size_t l) { return stol(string(s, l), nullptr, 10); };
|
g["NUMBER"] = [](const char* s, size_t n) { return stol(string(s, n), nullptr, 10); };
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
long val;
|
long val;
|
||||||
auto r = g[start].parse_with_value("1+2*3*(4-5+6)/7-8", val);
|
auto r = g[start].parse_and_get_value("1+2*3*(4-5+6)/7-8", val);
|
||||||
|
|
||||||
REQUIRE(r.ret == true);
|
REQUIRE(r.ret == true);
|
||||||
REQUIRE(val == -3);
|
REQUIRE(val == -3);
|
||||||
@ -410,22 +410,22 @@ TEST_CASE("Calculator test3", "[general]")
|
|||||||
// Setup actions
|
// Setup actions
|
||||||
parser["EXPRESSION"] = reduce;
|
parser["EXPRESSION"] = reduce;
|
||||||
parser["TERM"] = reduce;
|
parser["TERM"] = reduce;
|
||||||
parser["TERM_OPERATOR"] = [](const char* s, size_t l) { return (char)*s; };
|
parser["TERM_OPERATOR"] = [](const char* s, size_t n) { return (char)*s; };
|
||||||
parser["FACTOR_OPERATOR"] = [](const char* s, size_t l) { return (char)*s; };
|
parser["FACTOR_OPERATOR"] = [](const char* s, size_t n) { return (char)*s; };
|
||||||
parser["NUMBER"] = [](const char* s, size_t l) { return stol(string(s, l), nullptr, 10); };
|
parser["NUMBER"] = [](const char* s, size_t n) { return stol(string(s, n), nullptr, 10); };
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
long val;
|
long val;
|
||||||
auto ret = parser.parse_with_value("1+2*3*(4-5+6)/7-8", val);
|
auto ret = parser.parse("1+2*3*(4-5+6)/7-8", val);
|
||||||
|
|
||||||
REQUIRE(ret == true);
|
REQUIRE(ret == true);
|
||||||
REQUIRE(val == -3);
|
REQUIRE(val == -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exact(Grammar& g, const char* d, const char* s) {
|
bool exact(Grammar& g, const char* d, const char* s) {
|
||||||
auto l = strlen(s);
|
auto n = strlen(s);
|
||||||
auto r = g[d].parse(s, l);
|
auto r = g[d].parse(s, n);
|
||||||
return r.ret && r.len == l;
|
return r.ret && r.len == n;
|
||||||
}
|
}
|
||||||
|
|
||||||
Grammar& make_peg_grammar() {
|
Grammar& make_peg_grammar() {
|
||||||
|
Loading…
Reference in New Issue
Block a user