Changed namespace/class names.

This commit is contained in:
yhirose 2015-08-10 16:37:56 -04:00
parent 23737a716b
commit b9c9216788
10 changed files with 181 additions and 181 deletions

View File

@ -7,7 +7,7 @@ C++11 header-only [PEG](http://en.wikipedia.org/wiki/Parsing_expression_grammar)
The PEG syntax is well described on page 2 in the [document](http://pdos.csail.mit.edu/papers/parsing:popl04.pdf). *cpp-peglib* also supports the following additional syntax for now:
* `<` ... `>` (Anchor operator)
* `<` ... `>` (Token boundary operator)
* `$<` ... `>` (Capture operator)
* `$name<` ... `>` (Named capture operator)
* `~` (Ignore operator)
@ -25,7 +25,7 @@ This is a simple calculator sample. It shows how to define grammar, associate sa
#include <peglib.h>
#include <assert.h>
using namespace peglib;
using namespace peg;
using namespace std;
int main(void) {
@ -38,7 +38,7 @@ int main(void) {
Number <- [0-9]+
)";
peg parser(syntax);
parser parser(syntax);
// (3) Setup an action
parser["Additive"] = [](const SemanticValues& sv) {
@ -111,13 +111,13 @@ struct SemanticValues : protected std::vector<SemanticValue>
}
```
`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.
`peg::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 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.
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 *token boundary* operators. Each token boundary operator creates a semantic value that contains `const char*` of the position. It could be useful to eliminate unnecessary characters.
```c++
auto syntax = R"(
@ -139,7 +139,7 @@ auto ret = pg.parse(" token1, token2 ");
We can ignore unnecessary semantic values from the list by using `~` operator.
```c++
peglib::peg parser(
peg::pegparser parser(
" ROOT <- _ ITEM (',' _ ITEM _)* "
" ITEM <- ([a-z])+ "
" ~_ <- [ \t]* "
@ -155,22 +155,22 @@ auto ret = parser.parse(" item1, item2 ");
The following grammar is same as the above.
```c++
peglib::peg parser(
peg::parser parser(
" ROOT <- ~_ ITEM (',' ~_ ITEM ~_)* "
" ITEM <- ([a-z])+ "
" _ <- [ \t]* "
);
```
*Semantic predicate* support is available. We can do it by throwing a `peglib::parse_error` exception in a semantic action.
*Semantic predicate* support is available. We can do it by throwing a `peg::parse_error` exception in a semantic action.
```c++
peglib::peg parser("NUMBER <- [0-9]+");
peg::parser parser("NUMBER <- [0-9]+");
parser["NUMBER"] = [](const SemanticValues& sv) {
auto val = stol(sv.str(), nullptr, 10);
if (val != 100) {
throw peglib::parse_error("value error!!");
throw peg::parse_error("value error!!");
}
return val;
};
@ -189,12 +189,12 @@ Simple interface
*cpp-peglib* provides std::regex-like simple interface for trivial tasks.
`peglib::peg_match` tries to capture strings in the `$< ... >` operator and store them into `peglib::match` object.
`peg::peg_match` tries to capture strings in the `$< ... >` operator and store them into `peg::match` object.
```c++
peglib::match m;
peg::match m;
auto ret = peglib::peg_match(
auto ret = peg::peg_match(
R"(
ROOT <- _ ('[' $< TAG_NAME > ']' _)*
TAG_NAME <- (!']' .)+
@ -213,9 +213,9 @@ assert(m.str(3) == "tag-3");
It also supports named capture with the `$name<` ... `>` operator.
```c++
peglib::match m;
peg::match m;
auto ret = peglib::peg_match(
auto ret = peg::peg_match(
R"(
ROOT <- _ ('[' $test< TAG_NAME > ']' _)*
TAG_NAME <- (!']' .)+
@ -235,7 +235,7 @@ REQUIRE(m.str(cap[2]) == "tag-3");
There are some ways to *search* a peg pattern in a document.
```c++
using namespace peglib;
using namespace peg;
auto syntax = R"(
ROOT <- '[' $< [a-z0-9]+ > ']'
@ -243,8 +243,8 @@ auto syntax = R"(
auto s = " [tag1] [tag2] [tag3] ";
// peglib::peg_search
peg pg(syntax);
// peg::peg_search
parser pg(syntax);
size_t pos = 0;
auto n = strlen(s);
match m;
@ -254,7 +254,7 @@ while (peg_search(pg, s + pos, n - pos, m)) {
pos += m.length();
}
// peglib::peg_token_iterator
// peg::peg_token_iterator
peg_token_iterator it(syntax, s);
while (it != peg_token_iterator()) {
cout << it->str() << endl; // entire match
@ -262,7 +262,7 @@ while (it != peg_token_iterator()) {
++it;
}
// peglib::peg_token_range
// peg::peg_token_range
for (auto& m: peg_token_range(syntax, s)) {
cout << m.str() << endl; // entire match
cout << m.str(1) << endl; // submatch #1
@ -275,7 +275,7 @@ Make a parser with parser operators
Instead of makeing a parser by parsing PEG syntax text, we can also construct a parser by hand with *parser operators*. Here is an example:
```c++
using namespace peglib;
using namespace peg;
using namespace std;
vector<string> tags;
@ -305,7 +305,7 @@ The following are available operators:
| cls | Character class |
| chr | Character |
| dot | Any character |
| anc | Anchor character |
| tok | Token boundary |
| ign | Ignore semantic value |
| cap | Capture character |
| usr | User defiend parser |
@ -337,7 +337,7 @@ Rules additional_rules = {
}
};
peg g = peg(syntax, additional_rules);
auto g = parser(syntax, additional_rules);
assert(g.parse(" Hello BNF! "));
```

View File

@ -9,7 +9,7 @@
#include <iostream>
#include <cstdlib>
using namespace peglib;
using namespace peg;
using namespace std;
int main(int argc, const char** argv)
@ -34,7 +34,7 @@ int main(int argc, const char** argv)
return result;
};
peg parser(R"(
parser parser(R"(
EXPRESSION <- _ TERM (TERM_OPERATOR TERM)*
TERM <- FACTOR (FACTOR_OPERATOR FACTOR)*
FACTOR <- NUMBER / '(' _ EXPRESSION ')' _

View File

@ -9,7 +9,7 @@
#include <iostream>
#include <cstdlib>
using namespace peglib;
using namespace peg;
using namespace std;
//

View File

@ -9,7 +9,7 @@
#include <iostream>
#include <cstdlib>
using namespace peglib;
using namespace peg;
using namespace std;
int main(int argc, const char** argv)
@ -39,7 +39,7 @@ int main(int argc, const char** argv)
}
};
peg parser(R"(
parser parser(R"(
EXPRESSION <- _ TERM (TERM_OPERATOR TERM)*
TERM <- FACTOR (FACTOR_OPERATOR FACTOR)*
FACTOR <- NUMBER / '(' _ EXPRESSION ')' _

View File

@ -86,9 +86,9 @@ const auto grammar_ = R"(
)";
inline peglib::peg& get_parser()
inline peg::parser& get_parser()
{
static peglib::peg parser;
static peg::parser parser;
static bool initialized = false;
if (!initialized) {
@ -337,7 +337,7 @@ struct Value
}
Type type;
peglib::any v;
peg::any v;
};
struct Symbol {
@ -408,7 +408,7 @@ struct Environment
std::map<std::string, Symbol> dictionary;
};
typedef std::function<void (const peglib::Ast& ast, Environment& env, bool force_to_break)> Debugger;
typedef std::function<void (const peg::Ast& ast, Environment& env, bool force_to_break)> Debugger;
inline bool ObjectValue::has(const std::string& name) const {
if (properties->find(name) == properties->end()) {
@ -544,7 +544,7 @@ struct Interpreter
: debugger_(debugger) {
}
Value exec(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value exec(const peg::Ast& ast, std::shared_ptr<Environment> env) {
try {
return eval(ast, env);
} catch (const Value& val) {
@ -553,8 +553,8 @@ struct Interpreter
}
private:
Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
using peglib::operator"" _;
Value eval(const peg::Ast& ast, std::shared_ptr<Environment> env) {
using peg::operator"" _;
if (debugger_) {
if (ast.original_tag == "STATEMENT"_) {
@ -598,7 +598,7 @@ private:
throw std::logic_error("invalid Ast type");
}
Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_statements(const peg::Ast& ast, std::shared_ptr<Environment> env) {
if (ast.is_token) {
return eval(ast, env);
} else if (ast.nodes.empty()) {
@ -612,7 +612,7 @@ private:
return eval(**it, env);
}
Value eval_while(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_while(const peg::Ast& ast, std::shared_ptr<Environment> env) {
for (;;) {
auto cond = eval(*ast.nodes[0], env);
if (!cond.to_bool()) {
@ -623,7 +623,7 @@ private:
return Value();
}
Value eval_if(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_if(const peg::Ast& ast, std::shared_ptr<Environment> env) {
const auto& nodes = ast.nodes;
for (auto i = 0u; i < nodes.size(); i += 2) {
@ -640,7 +640,7 @@ private:
return Value();
}
Value eval_function(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_function(const peg::Ast& ast, std::shared_ptr<Environment> env) {
std::vector<FunctionValue::Parameter> params;
for (auto node: ast.nodes[0]->nodes) {
auto mut = node->nodes[0]->token == "mut";
@ -659,7 +659,7 @@ private:
));
};
Value eval_function_call(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
Value eval_function_call(const peg::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
const auto& f = val.to_function();
const auto& params = *f.params;
const auto& args = ast.nodes;
@ -686,7 +686,7 @@ private:
throw std::runtime_error(msg);
}
Value eval_array_reference(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
Value eval_array_reference(const peg::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
const auto& arr = val.to_array();
auto idx = eval(ast, env).to_long();
if (0 <= idx && idx < static_cast<long>(arr.values->size())) {
@ -697,7 +697,7 @@ private:
return val;
}
Value eval_property(const peglib::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
Value eval_property(const peg::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
const auto& obj = val.to_object();
auto name = ast.token;
if (!obj.has(name)) {
@ -717,8 +717,8 @@ private:
return prop;
}
Value eval_call(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
using peglib::operator"" _;
Value eval_call(const peg::Ast& ast, std::shared_ptr<Environment> env) {
using peg::operator"" _;
Value val = eval(*ast.nodes[0], env);
@ -736,11 +736,11 @@ private:
return std::move(val);
}
Value eval_block(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_block(const peg::Ast& ast, std::shared_ptr<Environment> env) {
return Value();
}
Value eval_logical_or(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_logical_or(const peg::Ast& ast, std::shared_ptr<Environment> env) {
assert(ast.nodes.size() > 1); // if the size is 1, thes node will be hoisted.
Value val;
for (auto node: ast.nodes) {
@ -752,7 +752,7 @@ private:
return std::move(val);
}
Value eval_logical_and(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_logical_and(const peg::Ast& ast, std::shared_ptr<Environment> env) {
Value val;
for (auto node: ast.nodes) {
val = eval(*node, env);
@ -763,7 +763,7 @@ private:
return std::move(val);
}
Value eval_condition(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_condition(const peg::Ast& ast, std::shared_ptr<Environment> env) {
assert(ast.nodes.size() == 3); // if the size is 1, thes node will be hoisted.
auto lhs = eval(*ast.nodes[0], env);
@ -779,22 +779,22 @@ private:
else { throw std::logic_error("invalid internal condition."); }
}
Value eval_unary_plus(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_unary_plus(const peg::Ast& ast, std::shared_ptr<Environment> env) {
assert(ast.nodes.size() == 2); // if the size is 1, thes node will be hoisted.
return eval(*ast.nodes[1], env);
}
Value eval_unary_minus(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_unary_minus(const peg::Ast& ast, std::shared_ptr<Environment> env) {
assert(ast.nodes.size() == 2); // if the size is 1, thes node will be hoisted.
return Value(eval(*ast.nodes[1], env).to_long() * -1);
}
Value eval_unary_not(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_unary_not(const peg::Ast& ast, std::shared_ptr<Environment> env) {
assert(ast.nodes.size() == 2); // if the size is 1, thes node will be hoisted.
return Value(!eval(*ast.nodes[1], env).to_bool());
}
Value eval_bin_expression(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_bin_expression(const peg::Ast& ast, std::shared_ptr<Environment> env) {
auto ret = eval(*ast.nodes[0], env).to_long();
for (auto i = 1u; i < ast.nodes.size(); i += 2) {
auto val = eval(*ast.nodes[i + 1], env).to_long();
@ -820,7 +820,7 @@ private:
return keywords.find(ident) != keywords.end();
}
Value eval_assignment(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_assignment(const peg::Ast& ast, std::shared_ptr<Environment> env) {
auto end = ast.nodes.size() - 1;
auto mut = ast.nodes[0]->token == "mut";
@ -837,7 +837,7 @@ private:
}
return std::move(val);
} else {
using peglib::operator"" _;
using peg::operator"" _;
Value lval = eval(*ast.nodes[1], env);
@ -882,11 +882,11 @@ private:
}
};
Value eval_identifier(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_identifier(const peg::Ast& ast, std::shared_ptr<Environment> env) {
return env->get(ast.token);
};
Value eval_object(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_object(const peg::Ast& ast, std::shared_ptr<Environment> env) {
ObjectValue obj;
for (auto i = 0u; i < ast.nodes.size(); i++) {
const auto& prop = *ast.nodes[i];
@ -898,7 +898,7 @@ private:
return Value(std::move(obj));
}
Value eval_array(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_array(const peg::Ast& ast, std::shared_ptr<Environment> env) {
ArrayValue arr;
for (auto i = 0u; i < ast.nodes.size(); i++) {
auto expr = ast.nodes[i];
@ -908,19 +908,19 @@ private:
return Value(std::move(arr));
}
Value eval_undefined(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_undefined(const peg::Ast& ast, std::shared_ptr<Environment> env) {
return Value();
};
Value eval_bool(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_bool(const peg::Ast& ast, std::shared_ptr<Environment> env) {
return Value(ast.token == "true");
};
Value eval_number(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_number(const peg::Ast& ast, std::shared_ptr<Environment> env) {
return Value(stol(ast.token));
};
Value eval_interpolated_string(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
Value eval_interpolated_string(const peg::Ast& ast, std::shared_ptr<Environment> env) {
std::string s;
for (auto node: ast.nodes) {
const auto& val = eval(*node, env);
@ -933,7 +933,7 @@ private:
return Value(std::move(s));
};
void eval_return(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
void eval_return(const peg::Ast& ast, std::shared_ptr<Environment> env) {
if (ast.nodes.empty()) {
throw Value();
} else {
@ -951,7 +951,7 @@ inline bool run(
size_t len,
Value& val,
std::vector<std::string>& msgs,
std::shared_ptr<peglib::Ast>& ast,
std::shared_ptr<peg::Ast>& ast,
Debugger debugger = nullptr)
{
try {
@ -964,7 +964,7 @@ inline bool run(
};
if (parser.parse_n(expr, len, ast, path.c_str())) {
ast = peglib::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY", "RETURN" }).optimize(ast);
ast = peg::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY", "RETURN" }).optimize(ast);
val = Interpreter(debugger).exec(*ast, env);
return true;
}

View File

@ -6,7 +6,7 @@
#include <vector>
using namespace culebra;
using namespace peglib;
using namespace peg;
using namespace std;
bool read_file(const char* path, vector<char>& buff)

View File

@ -10,7 +10,7 @@
#include <iostream>
#include <sstream>
using namespace peglib;
using namespace peg;
using namespace std;
/*
@ -331,7 +331,7 @@ private:
// compare <- expression compare_op expression
const auto& nodes = ast->nodes;
auto lval = eval_expression(nodes[0], env);
auto op = peglib::str2tag(nodes[1]->token.c_str());
auto op = peg::str2tag(nodes[1]->token.c_str());
auto rval = eval_expression(nodes[2], env);
switch (op) {
case "="_: return lval == rval;
@ -427,7 +427,7 @@ int main(int argc, const char** argv)
}
// Setup a PEG parser
peg parser(grammar);
parser parser(grammar);
parser.enable_ast<AstPL0>();
parser.log = [&](size_t ln, size_t col, const string& msg) {
cerr << format_error_message(path, ln, col, msg) << endl;

View File

@ -59,13 +59,13 @@ int main(int argc, const char** argv)
return -1;
}
peglib::peg peg;
peg::parser parser;
peg.log = [&](auto ln, auto col, const auto& msg) {
parser.log = [&](auto ln, auto col, const auto& msg) {
cerr << syntax_path << ":" << ln << ":" << col << ": " << msg << endl;
};
if (!peg.load_grammar(syntax.data(), syntax.size())) {
if (!parser.load_grammar(syntax.data(), syntax.size())) {
return -1;
}
@ -84,22 +84,22 @@ int main(int argc, const char** argv)
source_path = "[commendline]";
}
peg.log = [&](auto ln, auto col, const auto& msg) {
parser.log = [&](auto ln, auto col, const auto& msg) {
cerr << source_path << ":" << ln << ":" << col << ": " << msg << endl;
};
if (opt_ast) {
peg.enable_ast();
parser.enable_ast();
std::shared_ptr<peglib::Ast> ast;
if (!peg.parse_n(source.data(), source.size(), ast)) {
std::shared_ptr<peg::Ast> ast;
if (!parser.parse_n(source.data(), source.size(), ast)) {
return -1;
}
ast = peglib::AstOptimizer(opt_optimize_ast_nodes).optimize(ast);
peglib::AstPrint::print(ast);
ast = peg::AstOptimizer(opt_optimize_ast_nodes).optimize(ast);
peg::AstPrint::print(ast);
} else {
if (!peg.parse_n(source.data(), source.size())) {
if (!parser.parse_n(source.data(), source.size())) {
return -1;
}
}

100
peglib.h
View File

@ -23,7 +23,7 @@
#include <unordered_map>
#include <vector>
namespace peglib {
namespace peg {
extern void* enabler;
@ -846,10 +846,10 @@ private:
std::string name_;
};
class Anchor : public Ope
class TokenBoundary : public Ope
{
public:
Anchor(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
TokenBoundary(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
const auto& rule = *ope_;
@ -979,7 +979,7 @@ struct Ope::Visitor
virtual void visit(Character& ope) {}
virtual void visit(AnyCharacter& ope) {}
virtual void visit(Capture& ope) {}
virtual void visit(Anchor& ope) {}
virtual void visit(TokenBoundary& ope) {}
virtual void visit(Ignore& ope) {}
virtual void visit(User& ope) {}
virtual void visit(WeakHolder& ope) {}
@ -1005,7 +1005,7 @@ struct AssignIDToDefinition : public Ope::Visitor
void visit(AndPredicate& ope) override { ope.ope_->accept(*this); }
void visit(NotPredicate& ope) override { ope.ope_->accept(*this); }
void visit(Capture& ope) override { ope.ope_->accept(*this); }
void visit(Anchor& ope) override { ope.ope_->accept(*this); }
void visit(TokenBoundary& ope) override { ope.ope_->accept(*this); }
void visit(Ignore& ope) override { ope.ope_->accept(*this); }
void visit(WeakHolder& ope) override { ope.weak_.lock()->accept(*this); }
void visit(Holder& ope) override;
@ -1016,7 +1016,7 @@ struct AssignIDToDefinition : public Ope::Visitor
struct IsToken : public Ope::Visitor
{
IsToken() : has_anchor(false), has_rule(false) {}
IsToken() : has_token_boundary(false), has_rule(false) {}
void visit(Sequence& ope) override {
for (auto op: ope.opes_) {
@ -1032,16 +1032,16 @@ struct IsToken : public Ope::Visitor
void visit(OneOrMore& ope) override { ope.ope_->accept(*this); }
void visit(Option& ope) override { ope.ope_->accept(*this); }
void visit(Capture& ope) override { ope.ope_->accept(*this); }
void visit(Anchor& ope) override { has_anchor = true; }
void visit(TokenBoundary& ope) override { has_token_boundary = true; }
void visit(Ignore& ope) override { ope.ope_->accept(*this); }
void visit(WeakHolder& ope) override { ope.weak_.lock()->accept(*this); }
void visit(DefinitionReference& ope) override { has_rule = true; }
bool is_token() const {
return has_anchor || !has_rule;
return has_token_boundary || !has_rule;
}
bool has_anchor;
bool has_token_boundary;
bool has_rule;
};
@ -1219,8 +1219,8 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
size_t len;
any val;
const char* anchors = s;
size_t anchorn = n;
const char* token_boundary_s = s;
size_t token_boundary_n = n;
c.packrat(s, outer_->id, len, val, [&](any& val) {
auto& chldsv = c.push();
@ -1228,13 +1228,13 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
const auto& rule = *ope_;
len = rule.parse(s, n, chldsv, c, dt);
anchorn = len;
token_boundary_n = len;
// Invoke action
if (success(len)) {
if (chldsv.s) {
anchors = chldsv.s;
anchorn = chldsv.n;
token_boundary_s = chldsv.s;
token_boundary_n = chldsv.n;
} else {
chldsv.s = s;
chldsv.n = len;
@ -1255,7 +1255,7 @@ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context
});
if (success(len) && !outer_->ignoreSemanticValue) {
sv.emplace_back(val, outer_->name.c_str(), anchors, anchorn);
sv.emplace_back(val, outer_->name.c_str(), token_boundary_s, token_boundary_n);
}
if (fail(len) && outer_->error_message && !c.message_pos) {
@ -1304,7 +1304,7 @@ inline void CharacterClass::accept(Visitor& v) { v.visit(*this); }
inline void Character::accept(Visitor& v) { v.visit(*this); }
inline void AnyCharacter::accept(Visitor& v) { v.visit(*this); }
inline void Capture::accept(Visitor& v) { v.visit(*this); }
inline void Anchor::accept(Visitor& v) { v.visit(*this); }
inline void TokenBoundary::accept(Visitor& v) { v.visit(*this); }
inline void Ignore::accept(Visitor& v) { v.visit(*this); }
inline void User::accept(Visitor& v) { v.visit(*this); }
inline void WeakHolder::accept(Visitor& v) { v.visit(*this); }
@ -1379,8 +1379,8 @@ inline std::shared_ptr<Ope> cap(const std::shared_ptr<Ope>& ope, MatchAction ma)
return std::make_shared<Capture>(ope, ma, (size_t)-1, std::string());
}
inline std::shared_ptr<Ope> anc(const std::shared_ptr<Ope>& ope) {
return std::make_shared<Anchor>(ope);
inline std::shared_ptr<Ope> tok(const std::shared_ptr<Ope>& ope) {
return std::make_shared<TokenBoundary>(ope);
}
inline std::shared_ptr<Ope> ign(const std::shared_ptr<Ope>& ope) {
@ -1422,7 +1422,7 @@ typedef std::function<void (size_t, size_t, const std::string&)> Log;
typedef std::unordered_map<std::string, std::shared_ptr<Ope>> Rules;
class PEGParser
class ParserGenerator
{
public:
static std::shared_ptr<Grammar> parse(
@ -1453,12 +1453,12 @@ public:
}
private:
static PEGParser& get_instance() {
static PEGParser instance;
static ParserGenerator& get_instance() {
static ParserGenerator instance;
return instance;
}
PEGParser() {
ParserGenerator() {
make_grammar();
setup_actions();
}
@ -1536,7 +1536,7 @@ private:
void visit(Capture& ope) override {
ope.ope_->accept(*this);
}
void visit(Anchor& ope) override {
void visit(TokenBoundary& ope) override {
ope.ope_->accept(*this);
}
void visit(Ignore& ope) override {
@ -1591,10 +1591,10 @@ private:
g["IdentStart"] <= cls("a-zA-Z_\x80-\xff");
g["IdentRest"] <= cho(g["IdentStart"], cls("0-9"));
g["Literal"] <= cho(seq(cls("'"), anc(zom(seq(npd(cls("'")), g["Char"]))), cls("'"), g["Spacing"]),
seq(cls("\""), anc(zom(seq(npd(cls("\"")), g["Char"]))), cls("\""), g["Spacing"]));
g["Literal"] <= cho(seq(cls("'"), tok(zom(seq(npd(cls("'")), g["Char"]))), cls("'"), g["Spacing"]),
seq(cls("\""), tok(zom(seq(npd(cls("\"")), g["Char"]))), cls("\""), g["Spacing"]));
g["Class"] <= seq(chr('['), anc(zom(seq(npd(chr(']')), g["Range"]))), chr(']'), g["Spacing"]);
g["Class"] <= seq(chr('['), tok(zom(seq(npd(chr(']')), g["Range"]))), chr(']'), g["Spacing"]);
g["Range"] <= cho(seq(g["Char"], chr('-'), g["Char"]), g["Char"]);
g["Char"] <= cho(seq(chr('\\'), cls("nrt'\"[]\\")),
@ -1623,7 +1623,7 @@ private:
g["Begin"] <= seq(chr('<'), g["Spacing"]);
g["End"] <= seq(chr('>'), g["Spacing"]);
g["BeginCap"] <= seq(chr('$'), anc(opt(g["Identifier"])), chr('<'), g["Spacing"]);
g["BeginCap"] <= seq(chr('$'), tok(opt(g["Identifier"])), chr('<'), g["Spacing"]);
g["EndCap"] <= seq(lit(">"), g["Spacing"]);
g["IGNORE"] <= chr('~');
@ -1742,8 +1742,8 @@ private:
case 1: { // (Expression)
return sv[1].get<std::shared_ptr<Ope>>();
}
case 2: { // Anchor
return anc(sv[1].get<std::shared_ptr<Ope>>());
case 2: { // TokenBoundary
return tok(sv[1].get<std::shared_ptr<Ope>>());
}
case 3: { // Capture
auto name = std::string(sv[0].s, sv[0].n);
@ -2100,33 +2100,33 @@ struct EmptyType {};
typedef AstBase<EmptyType> Ast;
/*-----------------------------------------------------------------------------
* peg
* parser
*---------------------------------------------------------------------------*/
class peg
class parser
{
public:
peg() = default;
parser() = default;
peg(const char* s, size_t n, const Rules& rules) {
parser(const char* s, size_t n, const Rules& rules) {
load_grammar(s, n, rules);
}
peg(const char* s, const Rules& rules)
: peg(s, strlen(s), rules) {}
parser(const char* s, const Rules& rules)
: parser(s, strlen(s), rules) {}
peg(const char* s, size_t n)
: peg(s, n, Rules()) {}
parser(const char* s, size_t n)
: parser(s, n, Rules()) {}
peg(const char* s)
: peg(s, strlen(s), Rules()) {}
parser(const char* s)
: parser(s, strlen(s), Rules()) {}
operator bool() {
return grammar_ != nullptr;
}
bool load_grammar(const char* s, size_t n, const Rules& rules) {
grammar_ = PEGParser::parse(
grammar_ = ParserGenerator::parse(
s, n,
rules,
start_,
@ -2253,7 +2253,7 @@ public:
}
template <typename T = Ast>
peg& enable_ast() {
parser& enable_ast() {
for (auto& x: *grammar_) {
const auto& name = x.first;
auto& rule = x.second;
@ -2396,7 +2396,7 @@ struct match
inline bool peg_match(const char* syntax, const char* s, match& m) {
m.matches.clear();
peg pg(syntax);
parser pg(syntax);
pg.match_action = [&](const char* s, size_t n, size_t id, const std::string& name) {
m.matches.push_back(match::Item{ s, n, id, name });
};
@ -2411,11 +2411,11 @@ inline bool peg_match(const char* syntax, const char* s, match& m) {
}
inline bool peg_match(const char* syntax, const char* s) {
peg pg(syntax);
return pg.parse(s);
parser parser(syntax);
return parser.parse(s);
}
inline bool peg_search(peg& pg, const char* s, size_t n, match& m) {
inline bool peg_search(parser& pg, const char* s, size_t n, match& m) {
m.matches.clear();
pg.match_action = [&](const char* s, size_t n, size_t id, const std::string& name) {
@ -2432,18 +2432,18 @@ inline bool peg_search(peg& pg, const char* s, size_t n, match& m) {
return false;
}
inline bool peg_search(peg& pg, const char* s, match& m) {
inline bool peg_search(parser& pg, const char* s, match& m) {
auto n = strlen(s);
return peg_search(pg, s, n, m);
}
inline bool peg_search(const char* syntax, const char* s, size_t n, match& m) {
peg pg(syntax);
parser pg(syntax);
return peg_search(pg, s, n, m);
}
inline bool peg_search(const char* syntax, const char* s, match& m) {
peg pg(syntax);
parser pg(syntax);
auto n = strlen(s);
return peg_search(pg, s, n, m);
}
@ -2513,7 +2513,7 @@ private:
}
}
peg peg_;
parser peg_;
const char* s_;
size_t l_;
size_t pos_;
@ -2549,7 +2549,7 @@ private:
peg_token_iterator end_iter;
};
} // namespace peglib
} // namespace peg
#endif

View File

@ -7,7 +7,7 @@
TEST_CASE("Simple syntax test", "[general]")
{
peglib::peg parser(
peg::parser parser(
" ROOT <- _ "
" _ <- ' ' "
);
@ -18,14 +18,14 @@ TEST_CASE("Simple syntax test", "[general]")
TEST_CASE("Empty syntax test", "[general]")
{
peglib::peg parser("");
peg::parser parser("");
bool ret = parser;
REQUIRE(ret == false);
}
TEST_CASE("String capture test", "[general]")
{
peglib::peg parser(
peg::parser parser(
" ROOT <- _ ('[' TAG_NAME ']' _)* "
" TAG_NAME <- (!']' .)+ "
" _ <- [ \t]* "
@ -33,7 +33,7 @@ TEST_CASE("String capture test", "[general]")
std::vector<std::string> tags;
parser["TAG_NAME"] = [&](const peglib::SemanticValues& sv) {
parser["TAG_NAME"] = [&](const peg::SemanticValues& sv) {
tags.push_back(sv.str());
};
@ -48,8 +48,8 @@ TEST_CASE("String capture test", "[general]")
TEST_CASE("String capture test with match", "[general]")
{
peglib::match m;
auto ret = peglib::peg_match(
peg::match m;
auto ret = peg::peg_match(
" ROOT <- _ ('[' $< TAG_NAME > ']' _)* "
" TAG_NAME <- (!']' .)+ "
" _ <- [ \t]* ",
@ -63,7 +63,7 @@ TEST_CASE("String capture test with match", "[general]")
REQUIRE(m.str(3) == "tag-3");
}
using namespace peglib;
using namespace peg;
using namespace std;
TEST_CASE("String capture test2", "[general]")
@ -93,7 +93,7 @@ TEST_CASE("String capture test3", "[general]")
" _ <- [ \t\r\n]* "
;
peg pg(syntax);
parser pg(syntax);
std::vector<std::string> tags;
@ -112,9 +112,9 @@ TEST_CASE("String capture test3", "[general]")
TEST_CASE("Named capture test", "[general]")
{
peglib::match m;
peg::match m;
auto ret = peglib::peg_match(
auto ret = peg::peg_match(
" ROOT <- _ ('[' $test< TAG_NAME > ']' _)* "
" TAG_NAME <- (!']' .)+ "
" _ <- [ \t]* ",
@ -180,14 +180,14 @@ TEST_CASE("Visit test", "[general]")
TEST_CASE("Token check test", "[general]")
{
peg parser(
parser parser(
" EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* "
" TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* "
" FACTOR <- NUMBER / '(' _ EXPRESSION ')' _ "
" TERM_OPERATOR <- < [-+] > _ "
" FACTOR_OPERATOR <- < [/*] > _ "
" NUMBER <- < [0-9]+ > _ "
" ~_ <- [ \t\r\n]* "
" _ <- [ \t\r\n]* "
);
REQUIRE(parser["EXPRESSION"].is_token == false);
@ -199,7 +199,7 @@ TEST_CASE("Token check test", "[general]")
TEST_CASE("Lambda action test", "[general]")
{
peg parser(
parser parser(
" START <- (CHAR)* "
" CHAR <- . ");
@ -215,7 +215,7 @@ TEST_CASE("Lambda action test", "[general]")
TEST_CASE("Skip token test", "[general]")
{
peglib::peg parser(
peg::parser parser(
" ROOT <- _ ITEM (',' _ ITEM _)* "
" ITEM <- ([a-z0-9])+ "
" ~_ <- [ \t]* "
@ -232,7 +232,7 @@ TEST_CASE("Skip token test", "[general]")
TEST_CASE("Backtracking test", "[general]")
{
peg parser(
parser parser(
" START <- PAT1 / PAT2 "
" PAT1 <- HELLO ' One' "
" PAT2 <- HELLO ' Two' "
@ -253,7 +253,7 @@ TEST_CASE("Backtracking test", "[general]")
TEST_CASE("Backtracking with AST", "[general]")
{
peg parser(R"(
parser parser(R"(
S <- A? B (A B)* A
A <- 'a'
B <- 'b'
@ -268,7 +268,7 @@ TEST_CASE("Backtracking with AST", "[general]")
TEST_CASE("Octal/Hex value test", "[general]")
{
peglib::peg parser(
peg::parser parser(
R"( ROOT <- '\132\x7a' )"
);
@ -281,7 +281,7 @@ TEST_CASE("mutable lambda test", "[general]")
{
vector<string> vec;
peg pg("ROOT <- 'mutable lambda test'");
parser pg("ROOT <- 'mutable lambda test'");
// This test makes sure if the following code can be compiled.
pg["TOKEN"] = [=](const SemanticValues& sv) mutable {
@ -297,7 +297,7 @@ TEST_CASE("Simple calculator test", "[general]")
" Primary <- '(' Additive ')' / Number "
" Number <- [0-9]+ ";
peg parser(syntax);
parser parser(syntax);
parser["Additive"] = [](const SemanticValues& sv) {
switch (sv.choice) {
@ -382,7 +382,7 @@ TEST_CASE("Calculator test2", "[general]")
;
string start;
auto grammar = PEGParser::parse(syntax, strlen(syntax), start, nullptr, nullptr);
auto grammar = ParserGenerator::parse(syntax, strlen(syntax), start, nullptr, nullptr);
auto& g = *grammar;
// Setup actions
@ -417,7 +417,7 @@ TEST_CASE("Calculator test2", "[general]")
TEST_CASE("Calculator test3", "[general]")
{
// Parse syntax
peg parser(
parser parser(
" # Grammar for Calculator...\n "
" EXPRESSION <- TERM (TERM_OPERATOR TERM)* "
" TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* "
@ -458,7 +458,7 @@ TEST_CASE("Calculator test3", "[general]")
TEST_CASE("Calculator test with AST", "[general]")
{
peg parser(
parser parser(
" EXPRESSION <- _ TERM (TERM_OPERATOR TERM)* "
" TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* "
" FACTOR <- NUMBER / '(' _ EXPRESSION ')' _ "
@ -492,7 +492,7 @@ TEST_CASE("Calculator test with AST", "[general]")
shared_ptr<Ast> ast;
auto ret = parser.parse("1+2*3*(4-5+6)/7-8", ast);
ast = peglib::AstOptimizer(true).optimize(ast);
ast = peg::AstOptimizer(true).optimize(ast);
auto val = eval(*ast);
REQUIRE(ret == true);
@ -501,7 +501,7 @@ TEST_CASE("Calculator test with AST", "[general]")
TEST_CASE("Ignore semantic value test", "[general]")
{
peg parser(
parser parser(
" START <- ~HELLO WORLD "
" HELLO <- 'Hello' _ "
" WORLD <- 'World' _ "
@ -520,7 +520,7 @@ TEST_CASE("Ignore semantic value test", "[general]")
TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]")
{
peg parser(
parser parser(
" START <- _ !DUMMY HELLO_WORLD '.' "
" HELLO_WORLD <- HELLO 'World' _ "
" HELLO <- 'Hello' _ "
@ -540,7 +540,7 @@ TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]")
TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]")
{
peg parser(
parser parser(
" START <- _ &HELLO HELLO_WORLD '.' "
" HELLO_WORLD <- HELLO 'World' _ "
" HELLO <- 'Hello' _ "
@ -559,7 +559,7 @@ TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]")
TEST_CASE("Definition duplicates test", "[general]")
{
peg parser(
parser parser(
" A <- ''"
" A <- ''"
);
@ -569,7 +569,7 @@ TEST_CASE("Definition duplicates test", "[general]")
TEST_CASE("Left recursive test", "[left recursive]")
{
peg parser(
parser parser(
" A <- A 'a'"
" B <- A 'a'"
);
@ -579,7 +579,7 @@ TEST_CASE("Left recursive test", "[left recursive]")
TEST_CASE("Left recursive with option test", "[left recursive]")
{
peg parser(
parser parser(
" A <- 'a' / 'b'? B 'c' "
" B <- A "
);
@ -589,7 +589,7 @@ TEST_CASE("Left recursive with option test", "[left recursive]")
TEST_CASE("Left recursive with zom test", "[left recursive]")
{
peg parser(
parser parser(
" A <- 'a'* A* "
);
@ -598,7 +598,7 @@ TEST_CASE("Left recursive with zom test", "[left recursive]")
TEST_CASE("Left recursive with empty string test", "[left recursive]")
{
peg parser(
parser parser(
" A <- '' A"
);
@ -626,7 +626,7 @@ TEST_CASE("User rule test", "[user rule]")
}
};
peg g = peg(syntax, rules);
auto g = parser(syntax, rules);
REQUIRE(g.parse(" Hello BNF! ") == true);
}
@ -634,7 +634,7 @@ TEST_CASE("User rule test", "[user rule]")
TEST_CASE("Semantic predicate test", "[predicate]")
{
peg parser("NUMBER <- [0-9]+");
parser parser("NUMBER <- [0-9]+");
parser["NUMBER"] = [](const SemanticValues& sv) {
auto val = stol(sv.str(), nullptr, 10);
@ -655,7 +655,7 @@ TEST_CASE("Semantic predicate test", "[predicate]")
TEST_CASE("Japanese character", "[unicode]")
{
peglib::peg parser(R"(
peg::parser parser(R"(
<- ? ''
<-
<-
@ -678,18 +678,18 @@ bool exact(Grammar& g, const char* d, const char* s) {
}
Grammar& make_peg_grammar() {
return PEGParser::grammar();
return ParserGenerator::grammar();
}
TEST_CASE("PEG Grammar", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Grammar", " Definition <- a / ( b c ) / d \n rule2 <- [a-zA-Z][a-z0-9-]+ ") == true);
}
TEST_CASE("PEG Definition", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Definition", "Definition <- a / (b c) / d ") == true);
REQUIRE(exact(g, "Definition", "Definition <- a / b c / d ") == true);
REQUIRE(exact(g, "Definition", "Definition ") == false);
@ -700,7 +700,7 @@ TEST_CASE("PEG Definition", "[peg]")
TEST_CASE("PEG Expression", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Expression", "a / (b c) / d ") == true);
REQUIRE(exact(g, "Expression", "a / b c / d ") == true);
REQUIRE(exact(g, "Expression", "a b ") == true);
@ -711,7 +711,7 @@ TEST_CASE("PEG Expression", "[peg]")
TEST_CASE("PEG Sequence", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Sequence", "a b c d ") == true);
REQUIRE(exact(g, "Sequence", "") == true);
REQUIRE(exact(g, "Sequence", "!") == false);
@ -721,7 +721,7 @@ TEST_CASE("PEG Sequence", "[peg]")
TEST_CASE("PEG Prefix", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Prefix", "&[a]") == true);
REQUIRE(exact(g, "Prefix", "![']") == true);
REQUIRE(exact(g, "Prefix", "-[']") == false);
@ -731,7 +731,7 @@ TEST_CASE("PEG Prefix", "[peg]")
TEST_CASE("PEG Suffix", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Suffix", "aaa ") == true);
REQUIRE(exact(g, "Suffix", "aaa? ") == true);
REQUIRE(exact(g, "Suffix", "aaa* ") == true);
@ -744,7 +744,7 @@ TEST_CASE("PEG Suffix", "[peg]")
TEST_CASE("PEG Primary", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Primary", "_Identifier0_ ") == true);
REQUIRE(exact(g, "Primary", "_Identifier0_<-") == false);
REQUIRE(exact(g, "Primary", "( _Identifier0_ _Identifier1_ )") == true);
@ -760,7 +760,7 @@ TEST_CASE("PEG Primary", "[peg]")
TEST_CASE("PEG Identifier", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Identifier", "_Identifier0_ ") == true);
REQUIRE(exact(g, "Identifier", "0Identifier_ ") == false);
REQUIRE(exact(g, "Identifier", "Iden|t ") == false);
@ -771,7 +771,7 @@ TEST_CASE("PEG Identifier", "[peg]")
TEST_CASE("PEG IdentStart", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "IdentStart", "_") == true);
REQUIRE(exact(g, "IdentStart", "a") == true);
REQUIRE(exact(g, "IdentStart", "Z") == true);
@ -782,7 +782,7 @@ TEST_CASE("PEG IdentStart", "[peg]")
TEST_CASE("PEG IdentRest", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "IdentRest", "_") == true);
REQUIRE(exact(g, "IdentRest", "a") == true);
REQUIRE(exact(g, "IdentRest", "Z") == true);
@ -793,7 +793,7 @@ TEST_CASE("PEG IdentRest", "[peg]")
TEST_CASE("PEG Literal", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Literal", "'abc' ") == true);
REQUIRE(exact(g, "Literal", "'a\\nb\\tc' ") == true);
REQUIRE(exact(g, "Literal", "'a\\277\tc' ") == true);
@ -812,7 +812,7 @@ TEST_CASE("PEG Literal", "[peg]")
TEST_CASE("PEG Class", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Class", "[]") == true);
REQUIRE(exact(g, "Class", "[a]") == true);
REQUIRE(exact(g, "Class", "[a-z]") == true);
@ -832,7 +832,7 @@ TEST_CASE("PEG Class", "[peg]")
TEST_CASE("PEG Range", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Range", "a") == true);
REQUIRE(exact(g, "Range", "a-z") == true);
REQUIRE(exact(g, "Range", "az") == false);
@ -843,7 +843,7 @@ TEST_CASE("PEG Range", "[peg]")
TEST_CASE("PEG Char", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Char", "\\n") == true);
REQUIRE(exact(g, "Char", "\\r") == true);
REQUIRE(exact(g, "Char", "\\t") == true);
@ -876,7 +876,7 @@ TEST_CASE("PEG Char", "[peg]")
TEST_CASE("PEG Operators", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "LEFTARROW", "<-") == true);
REQUIRE(exact(g, "SLASH", "/ ") == true);
REQUIRE(exact(g, "AND", "& ") == true);
@ -891,7 +891,7 @@ TEST_CASE("PEG Operators", "[peg]")
TEST_CASE("PEG Comment", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Comment", "# Comment.\n") == true);
REQUIRE(exact(g, "Comment", "# Comment.") == false);
REQUIRE(exact(g, "Comment", " ") == false);
@ -900,7 +900,7 @@ TEST_CASE("PEG Comment", "[peg]")
TEST_CASE("PEG Space", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "Space", " ") == true);
REQUIRE(exact(g, "Space", "\t") == true);
REQUIRE(exact(g, "Space", "\n") == true);
@ -910,7 +910,7 @@ TEST_CASE("PEG Space", "[peg]")
TEST_CASE("PEG EndOfLine", "[peg]")
{
auto g = PEGParser::grammar();
auto g = ParserGenerator::grammar();
REQUIRE(exact(g, "EndOfLine", "\r\n") == true);
REQUIRE(exact(g, "EndOfLine", "\n") == true);
REQUIRE(exact(g, "EndOfLine", "\r") == true);