mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Simplefied code.
This commit is contained in:
parent
30971d28de
commit
2aa60699be
19
README.md
19
README.md
@ -41,19 +41,20 @@ int main(void) {
|
|||||||
peg parser(syntax);
|
peg parser(syntax);
|
||||||
|
|
||||||
// (3) Setup an action
|
// (3) Setup an action
|
||||||
parser["Additive"] = {
|
parser["Additive"] = [](const SemanticValues& sv) {
|
||||||
nullptr, // Default action
|
switch (sv.choice) {
|
||||||
[](const SemanticValues& sv) {
|
case 0: // "Multitive '+' Additive"
|
||||||
return sv[0].get<int>() + sv[1].get<int>(); // "Multitive '+' Additive"
|
return sv[0].get<int>() + sv[1].get<int>();
|
||||||
},
|
default: // "Multitive"
|
||||||
[](const SemanticValues& sv) { return sv[0]; } // "Multitive"
|
return sv[0].get<int>();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser["Multitive"] = [](const SemanticValues& sv) {
|
parser["Multitive"] = [](const SemanticValues& sv) {
|
||||||
switch (sv.choice) {
|
switch (sv.choice) {
|
||||||
case 0: // "Multitive '+' Additive"
|
case 0: // "Primary '*' Multitive"
|
||||||
return sv[0].get<int>() * sv[1].get<int>();
|
return sv[0].get<int>() * sv[1].get<int>();
|
||||||
default: // "Multitive"
|
default: // "Primary"
|
||||||
return sv[0].get<int>();
|
return sv[0].get<int>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -63,7 +64,7 @@ int main(void) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// (4) Parse
|
// (4) Parse
|
||||||
parser.packrat_parsing(true); // Enable packrat parsing.
|
parser.packrat_parsing(); // Enable packrat parsing.
|
||||||
|
|
||||||
int val;
|
int val;
|
||||||
parser.parse("(1+2)*3", val);
|
parser.parse("(1+2)*3", val);
|
||||||
|
127
peglib.h
127
peglib.h
@ -946,7 +946,7 @@ public:
|
|||||||
|
|
||||||
void accept(Visitor& v) override;
|
void accept(Visitor& v) override;
|
||||||
|
|
||||||
any reduce(const SemanticValues& sv, any& dt, const Action& action) const;
|
any reduce(const SemanticValues& sv, any& dt) const;
|
||||||
|
|
||||||
std::shared_ptr<Ope> ope_;
|
std::shared_ptr<Ope> ope_;
|
||||||
Definition* outer_;
|
Definition* outer_;
|
||||||
@ -1076,15 +1076,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Definition()
|
Definition()
|
||||||
: actions(1)
|
: ignoreSemanticValue(false)
|
||||||
, ignoreSemanticValue(false)
|
|
||||||
, enablePackratParsing(false)
|
, enablePackratParsing(false)
|
||||||
, is_token(false)
|
, is_token(false)
|
||||||
, holder_(std::make_shared<Holder>(this)) {}
|
, holder_(std::make_shared<Holder>(this)) {}
|
||||||
|
|
||||||
Definition(const Definition& rhs)
|
Definition(const Definition& rhs)
|
||||||
: name(rhs.name)
|
: name(rhs.name)
|
||||||
, actions(1)
|
|
||||||
, ignoreSemanticValue(false)
|
, ignoreSemanticValue(false)
|
||||||
, enablePackratParsing(false)
|
, enablePackratParsing(false)
|
||||||
, is_token(false)
|
, is_token(false)
|
||||||
@ -1095,7 +1093,6 @@ public:
|
|||||||
|
|
||||||
Definition(Definition&& rhs)
|
Definition(Definition&& rhs)
|
||||||
: name(std::move(rhs.name))
|
: name(std::move(rhs.name))
|
||||||
, actions(1)
|
|
||||||
, ignoreSemanticValue(rhs.ignoreSemanticValue)
|
, ignoreSemanticValue(rhs.ignoreSemanticValue)
|
||||||
, enablePackratParsing(rhs.enablePackratParsing)
|
, enablePackratParsing(rhs.enablePackratParsing)
|
||||||
, is_token(rhs.is_token)
|
, is_token(rhs.is_token)
|
||||||
@ -1105,8 +1102,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Definition(const std::shared_ptr<Ope>& ope)
|
Definition(const std::shared_ptr<Ope>& ope)
|
||||||
: actions(1)
|
: ignoreSemanticValue(false)
|
||||||
, ignoreSemanticValue(false)
|
|
||||||
, enablePackratParsing(false)
|
, enablePackratParsing(false)
|
||||||
, is_token(false)
|
, is_token(false)
|
||||||
, holder_(std::make_shared<Holder>(this))
|
, holder_(std::make_shared<Holder>(this))
|
||||||
@ -1182,14 +1178,8 @@ public:
|
|||||||
return parse_and_get_value(s, n, dt, val);
|
return parse_and_get_value(s, n, dt, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Definition& operator=(Action action) {
|
Definition& operator=(Action a) {
|
||||||
assert(!actions.empty());
|
action = a;
|
||||||
actions[0] = action;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Definition& operator=(std::initializer_list<Action> ini) {
|
|
||||||
actions = ini;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,7 +1200,7 @@ public:
|
|||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
size_t id;
|
size_t id;
|
||||||
std::vector<Action> actions;
|
Action action;
|
||||||
std::function<std::string ()> error_message;
|
std::function<std::string ()> error_message;
|
||||||
bool ignoreSemanticValue;
|
bool ignoreSemanticValue;
|
||||||
bool enablePackratParsing;
|
bool enablePackratParsing;
|
||||||
@ -1258,13 +1248,6 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
|
|||||||
|
|
||||||
// Invoke action
|
// Invoke action
|
||||||
if (success(len)) {
|
if (success(len)) {
|
||||||
assert(!outer_->actions.empty());
|
|
||||||
|
|
||||||
auto i = chldsv.choice + 1; // Index 0 is for the default action
|
|
||||||
const auto& action = (i < outer_->actions.size() && outer_->actions[i])
|
|
||||||
? outer_->actions[i]
|
|
||||||
: outer_->actions[0];
|
|
||||||
|
|
||||||
if (chldsv.s) {
|
if (chldsv.s) {
|
||||||
anchors = chldsv.s;
|
anchors = chldsv.s;
|
||||||
anchorn = chldsv.n;
|
anchorn = chldsv.n;
|
||||||
@ -1274,7 +1257,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val = reduce(chldsv, dt, action);
|
val = reduce(chldsv, dt);
|
||||||
} catch (const parse_error& e) {
|
} catch (const parse_error& e) {
|
||||||
if (e.what()) {
|
if (e.what()) {
|
||||||
c.message_pos = s;
|
c.message_pos = s;
|
||||||
@ -1299,9 +1282,9 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline any Holder::reduce(const SemanticValues& sv, any& dt, const Action& action) const {
|
inline any Holder::reduce(const SemanticValues& sv, any& dt) const {
|
||||||
if (action) {
|
if (outer_->action) {
|
||||||
return action(sv, dt);
|
return outer_->action(sv, dt);
|
||||||
} else if (sv.empty()) {
|
} else if (sv.empty()) {
|
||||||
return any();
|
return any();
|
||||||
} else {
|
} else {
|
||||||
@ -1674,8 +1657,8 @@ private:
|
|||||||
auto ignore = (sv.size() == 4);
|
auto ignore = (sv.size() == 4);
|
||||||
auto baseId = ignore ? 1 : 0;
|
auto baseId = ignore ? 1 : 0;
|
||||||
|
|
||||||
const auto& name = sv[baseId].val.get<std::string>();
|
const auto& name = sv[baseId].get<std::string>();
|
||||||
auto ope = sv[baseId + 2].val.get<std::shared_ptr<Ope>>();
|
auto ope = sv[baseId + 2].get<std::shared_ptr<Ope>>();
|
||||||
|
|
||||||
auto& grammar = *data.grammar;
|
auto& grammar = *data.grammar;
|
||||||
if (grammar.find(name) == grammar.end()) {
|
if (grammar.find(name) == grammar.end()) {
|
||||||
@ -1694,11 +1677,11 @@ private:
|
|||||||
|
|
||||||
g["Expression"] = [&](const SemanticValues& sv) {
|
g["Expression"] = [&](const SemanticValues& sv) {
|
||||||
if (sv.size() == 1) {
|
if (sv.size() == 1) {
|
||||||
return sv[0].val.get<std::shared_ptr<Ope>>();
|
return sv[0].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 < sv.size(); i++) {
|
for (auto i = 0u; i < sv.size(); i++) {
|
||||||
opes.push_back(sv[i].val.get<std::shared_ptr<Ope>>());
|
opes.push_back(sv[i].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;
|
||||||
@ -1707,11 +1690,11 @@ private:
|
|||||||
|
|
||||||
g["Sequence"] = [&](const SemanticValues& sv) {
|
g["Sequence"] = [&](const SemanticValues& sv) {
|
||||||
if (sv.size() == 1) {
|
if (sv.size() == 1) {
|
||||||
return sv[0].val.get<std::shared_ptr<Ope>>();
|
return sv[0].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: sv) {
|
for (const auto& x: sv) {
|
||||||
opes.push_back(x.val.get<std::shared_ptr<Ope>>());
|
opes.push_back(x.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;
|
||||||
@ -1721,11 +1704,11 @@ private:
|
|||||||
g["Prefix"] = [&](const SemanticValues& sv) {
|
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].get<std::shared_ptr<Ope>>();
|
||||||
} else {
|
} else {
|
||||||
assert(sv.size() == 2);
|
assert(sv.size() == 2);
|
||||||
auto tok = sv[0].val.get<char>();
|
auto tok = sv[0].get<char>();
|
||||||
ope = sv[1].val.get<std::shared_ptr<Ope>>();
|
ope = sv[1].get<std::shared_ptr<Ope>>();
|
||||||
if (tok == '&') {
|
if (tok == '&') {
|
||||||
ope = apd(ope);
|
ope = apd(ope);
|
||||||
} else { // '!'
|
} else { // '!'
|
||||||
@ -1736,12 +1719,12 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
g["Suffix"] = [&](const SemanticValues& sv) {
|
g["Suffix"] = [&](const SemanticValues& sv) {
|
||||||
auto ope = sv[0].val.get<std::shared_ptr<Ope>>();
|
auto ope = sv[0].get<std::shared_ptr<Ope>>();
|
||||||
if (sv.size() == 1) {
|
if (sv.size() == 1) {
|
||||||
return ope;
|
return ope;
|
||||||
} else {
|
} else {
|
||||||
assert(sv.size() == 2);
|
assert(sv.size() == 2);
|
||||||
auto tok = sv[1].val.get<char>();
|
auto tok = sv[1].get<char>();
|
||||||
if (tok == '?') {
|
if (tok == '?') {
|
||||||
return opt(ope);
|
return opt(ope);
|
||||||
} else if (tok == '*') {
|
} else if (tok == '*') {
|
||||||
@ -1752,45 +1735,40 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
g["Primary"].actions = {
|
g["Primary"] = [&](const SemanticValues& sv, any& dt) {
|
||||||
// Default
|
Data& data = *dt.get<Data*>();
|
||||||
[&](const SemanticValues& sv) {
|
switch (sv.choice) {
|
||||||
return sv[0];
|
case 0: { // Reference
|
||||||
},
|
auto ignore = (sv.size() == 2);
|
||||||
// Reference
|
auto baseId = ignore ? 1 : 0;
|
||||||
[&](const SemanticValues& sv, any& dt) {
|
|
||||||
Data& data = *dt.get<Data*>();
|
|
||||||
|
|
||||||
auto ignore = (sv.size() == 2);
|
const auto& ident = sv[baseId].get<std::string>();
|
||||||
auto baseId = ignore ? 1 : 0;
|
|
||||||
|
|
||||||
const auto& ident = sv[baseId].val.get<std::string>();
|
if (data.references.find(ident) == data.references.end()) {
|
||||||
|
data.references[ident] = sv.s; // for error handling
|
||||||
|
}
|
||||||
|
|
||||||
if (data.references.find(ident) == data.references.end()) {
|
if (ignore) {
|
||||||
data.references[ident] = sv.s; // for error handling
|
return ign(ref(*data.grammar, ident, sv.s));
|
||||||
|
} else {
|
||||||
|
return ref(*data.grammar, ident, sv.s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
case 1: { // (Expression)
|
||||||
if (ignore) {
|
return sv[1].get<std::shared_ptr<Ope>>();
|
||||||
return ign(ref(*data.grammar, ident, sv.s));
|
}
|
||||||
} else {
|
case 2: { // Anchor
|
||||||
return ref(*data.grammar, ident, sv.s);
|
auto ope = sv[1].get<std::shared_ptr<Ope>>();
|
||||||
|
return anc(ope);
|
||||||
|
}
|
||||||
|
case 3: { // Capture
|
||||||
|
auto name = std::string(sv[0].s, sv[0].n);
|
||||||
|
auto ope = sv[1].get<std::shared_ptr<Ope>>();
|
||||||
|
return cap(ope, data.match_action, ++data.capture_count, name);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return sv[0].get<std::shared_ptr<Ope>>();
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// (Expression)
|
|
||||||
[&](const SemanticValues& sv) {
|
|
||||||
return sv[1];
|
|
||||||
},
|
|
||||||
// Anchor
|
|
||||||
[&](const SemanticValues& sv) {
|
|
||||||
auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
|
|
||||||
return anc(ope);
|
|
||||||
},
|
|
||||||
// Capture
|
|
||||||
[&](const SemanticValues& sv, any& dt) {
|
|
||||||
Data& data = *dt.get<Data*>();
|
|
||||||
auto name = std::string(sv[0].s, sv[0].n);
|
|
||||||
auto ope = sv[1].val.get<std::shared_ptr<Ope>>();
|
|
||||||
return cap(ope, data.match_action, ++data.capture_count, name);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2249,10 +2227,9 @@ private:
|
|||||||
for (auto& x: *grammar_) {
|
for (auto& x: *grammar_) {
|
||||||
const auto& name = x.first;
|
const auto& name = x.first;
|
||||||
auto& rule = x.second;
|
auto& rule = x.second;
|
||||||
auto& action = rule.actions.front();
|
if (!rule.action) {
|
||||||
if (!action) {
|
|
||||||
auto is_token = rule.is_token;
|
auto is_token = rule.is_token;
|
||||||
action = [=](const SemanticValues& sv) {
|
rule.action = [=](const SemanticValues& sv) {
|
||||||
if (is_token) {
|
if (is_token) {
|
||||||
return std::make_shared<Ast>(name.c_str(), AstDefaultTag, std::string(sv.s, sv.n));
|
return std::make_shared<Ast>(name.c_str(), AstDefaultTag, std::string(sv.s, sv.n));
|
||||||
}
|
}
|
||||||
|
22
test/test.cc
22
test/test.cc
@ -284,21 +284,21 @@ TEST_CASE("Simple calculator test", "[general]")
|
|||||||
|
|
||||||
peg parser(syntax);
|
peg parser(syntax);
|
||||||
|
|
||||||
parser["Additive"] = {
|
parser["Additive"] = [](const SemanticValues& sv) {
|
||||||
// Default action
|
switch (sv.choice) {
|
||||||
nullptr,
|
case 0:
|
||||||
// Action for the first choice
|
return sv[0].get<int>() + sv[1].get<int>();
|
||||||
[](const SemanticValues& sv) { return sv[0].val.get<int>() + sv[1].val.get<int>(); },
|
default:
|
||||||
// Action for the second choice
|
return sv[0].get<int>();
|
||||||
[](const SemanticValues& sv) { return sv[0]; }
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser["Multitive"] = [](const SemanticValues& sv) {
|
parser["Multitive"] = [](const SemanticValues& sv) {
|
||||||
switch (sv.choice) {
|
switch (sv.choice) {
|
||||||
case 0: // Action for the first choice
|
case 0:
|
||||||
return sv[0].val.get<int>() * sv[1].val.get<int>();
|
return sv[0].get<int>() * sv[1].get<int>();
|
||||||
default: // Action for the second choice
|
default:
|
||||||
return sv[0].val.get<int>();
|
return sv[0].get<int>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user