Added set_logger

This commit is contained in:
yhirose 2022-09-03 08:12:12 -04:00
parent e5be920106
commit 66e5412b14
7 changed files with 77 additions and 78 deletions

View File

@ -115,9 +115,9 @@ auto grammar = R"(
parser parser;
parser.log = [](size_t line, size_t col, const string& msg, const string &rule) {
parser.set_logger([](size_t line, size_t col, const string& msg, const string &rule) {
cerr << line << ":" << col << ": " << msg << "\n";
};
});
auto ok = parser.load_grammar(grammar);
assert(ok);
@ -260,6 +260,18 @@ parser["RULE"].leave = [](const char* s, size_t n, size_t matchlen, any& value,
};
```
You can receive error information via a logger:
```cpp
parser.set_logger([](size_t line, size_t col, const string& msg) {
...
});
parser.set_logger([](size_t line, size_t col, const string& msg, const string &rule) {
...
});
```
Ignoring Whitespaces
--------------------

View File

@ -18,11 +18,10 @@ std::string escape_json(const std::string &s) {
return o.str();
}
std::function<void(size_t, size_t, const std::string &, const std::string &)>
std::function<void(size_t, size_t, const std::string &)>
makeJSONFormatter(std::string &json, bool &init) {
init = true;
return [&](size_t ln, size_t col, const std::string &msg,
const std::string &) mutable {
return [&](size_t ln, size_t col, const std::string &msg) mutable {
if (!init) { json += ","; }
json += "{";
json += R"("ln":)" + std::to_string(ln) + ",";
@ -37,7 +36,7 @@ makeJSONFormatter(std::string &json, bool &init) {
bool parse_grammar(const std::string &text, peg::parser &peg,
std::string &json) {
bool init;
peg.log = makeJSONFormatter(json, init);
peg.set_logger(makeJSONFormatter(json, init));
json += "[";
auto ret = peg.load_grammar(text.data(), text.size());
json += "]";
@ -48,7 +47,7 @@ bool parse_code(const std::string &text, peg::parser &peg, std::string &json,
std::shared_ptr<peg::Ast> &ast) {
peg.enable_ast();
bool init;
peg.log = makeJSONFormatter(json, init);
peg.set_logger(makeJSONFormatter(json, init));
json += "[";
auto ret = peg.parse_n(text.data(), text.size(), ast);
json += "]";

Binary file not shown.

View File

@ -105,10 +105,9 @@ int main(int argc, const char **argv) {
peg::parser parser;
parser.log = [&](size_t ln, size_t col, const string &msg,
const string & /*rule*/) {
parser.set_logger([&](size_t ln, size_t col, const string &msg) {
cerr << syntax_path << ":" << ln << ":" << col << ": " << msg << endl;
};
});
if (!parser.load_grammar(syntax.data(), syntax.size())) { return -1; }
@ -124,10 +123,9 @@ int main(int argc, const char **argv) {
source_path = path_list[1];
}
parser.log = [&](size_t ln, size_t col, const string &msg,
const string & /*rule*/) {
parser.set_logger([&](size_t ln, size_t col, const string &msg) {
cerr << source_path << ":" << ln << ":" << col << ": " << msg << endl;
};
});
if (opt_packrat) { parser.enable_packrat_parsing(); }

View File

@ -2504,8 +2504,7 @@ inline std::pair<size_t, size_t> SemanticValues::line_info() const {
return c_->line_info(sv_.data());
}
inline void ErrorInfo::output_log(const Log &log, const char *s,
size_t n) {
inline void ErrorInfo::output_log(const Log &log, const char *s, size_t n) {
if (message_pos) {
if (message_pos > last_output_pos) {
last_output_pos = message_pos;
@ -4443,8 +4442,8 @@ public:
operator bool() { return grammar_ != nullptr; }
bool load_grammar(const char *s, size_t n, const Rules &rules) {
grammar_ =
ParserGenerator::parse(s, n, rules, start_, enablePackratParsing_, log);
grammar_ = ParserGenerator::parse(s, n, rules, start_,
enablePackratParsing_, log_);
return grammar_ != nullptr;
}
@ -4463,7 +4462,7 @@ public:
bool parse_n(const char *s, size_t n, const char *path = nullptr) const {
if (grammar_ != nullptr) {
const auto &rule = (*grammar_)[start_];
auto result = rule.parse(s, n, path, log);
auto result = rule.parse(s, n, path, log_);
return post_process(s, n, result);
}
return false;
@ -4473,7 +4472,7 @@ public:
const char *path = nullptr) const {
if (grammar_ != nullptr) {
const auto &rule = (*grammar_)[start_];
auto result = rule.parse(s, n, dt, path, log);
auto result = rule.parse(s, n, dt, path, log_);
return post_process(s, n, result);
}
return false;
@ -4484,7 +4483,7 @@ public:
const char *path = nullptr) const {
if (grammar_ != nullptr) {
const auto &rule = (*grammar_)[start_];
auto result = rule.parse_and_get_value(s, n, val, path, log);
auto result = rule.parse_and_get_value(s, n, val, path, log_);
return post_process(s, n, result);
}
return false;
@ -4496,7 +4495,7 @@ public:
if (grammar_ != nullptr) {
const auto &rule = (*grammar_)[start_];
return post_process(s, n,
rule.parse_and_get_value(s, n, dt, val, path, log));
rule.parse_and_get_value(s, n, dt, val, path, log_));
}
return false;
}
@ -4612,12 +4611,18 @@ public:
return AstOptimizer(opt_mode, get_no_ast_opt_rules()).optimize(ast);
}
Log log;
void set_logger(Log log) { log_ = log; }
void set_logger(
std::function<void(size_t line, size_t col, const std::string &msg)>
log) {
log_ = [&](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) { log(line, col, msg); };
}
private:
bool post_process(const char *s, size_t n,
Definition::Result &r) const {
if (log && !r.ret) { r.error_info.output_log(log, s, n); }
bool post_process(const char *s, size_t n, Definition::Result &r) const {
if (log_ && !r.ret) { r.error_info.output_log(log_, s, n); }
return r.ret && !r.recovered;
}
@ -4632,6 +4637,7 @@ private:
std::shared_ptr<Grammar> grammar_;
std::string start_;
bool enablePackratParsing_ = false;
Log log_;
};
/*-----------------------------------------------------------------------------

View File

@ -247,12 +247,11 @@ TEST(GeneralTest, enter_leave_handlers_test) {
EXPECT_TRUE(parser.parse("hello=WORLD", dt));
EXPECT_TRUE(parser.parse("HELLO=WORLD", dt));
parser.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([&](size_t ln, size_t col, const std::string &msg) {
EXPECT_EQ(1, ln);
EXPECT_EQ(7, col);
EXPECT_EQ(message, msg);
};
});
parser.parse("hello=world", dt);
}
@ -1091,13 +1090,13 @@ TEST(GeneralTest, HeuristicErrorTokenTest) {
untyped_enum <- '' { message "invalid/missing enum type, expected one of 'sequence' or 'bitmask', got '%t'"}
)");
parser.log = [&](size_t ln, size_t col, const std::string &msg, const std::string & /*rule*/) {
parser.set_logger([&](size_t ln, size_t col, const std::string &msg) {
EXPECT_EQ(1, ln);
EXPECT_EQ(6, col);
EXPECT_EQ("invalid/missing enum type, expected one of 'sequence' or "
"'bitmask', got 'sequencer'",
msg);
};
});
auto ret = parser.parse("enum sequencer");
EXPECT_FALSE(ret);

View File

@ -853,12 +853,11 @@ TEST(PredicateTest, Semantic_predicate_test) {
EXPECT_TRUE(parser.parse("100", val));
EXPECT_EQ(100, val);
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
EXPECT_EQ(1, line);
EXPECT_EQ(1, col);
EXPECT_EQ("value error!!", msg);
};
});
EXPECT_FALSE(parser.parse("200", val));
}
@ -879,12 +878,11 @@ is_symbol <- Name { check_symbol var_table }
ref aaa
ref bbb
)";
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
EXPECT_EQ(3, line);
EXPECT_EQ(5, col);
EXPECT_EQ("'bbb' doesn't exist.", msg);
};
});
EXPECT_FALSE(parser.parse(source));
}
@ -893,12 +891,11 @@ ref bbb
ref aaa
decl aaa
)";
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
EXPECT_EQ(3, line);
EXPECT_EQ(6, col);
EXPECT_EQ("'aaa' already exists.", msg);
};
});
EXPECT_FALSE(parser.parse(source));
}
}
@ -966,12 +963,11 @@ typedef __off64_t __loff_t;
typedef long __off64_t;
typedef __off64_T __loff_t;
)";
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
EXPECT_EQ(3, line);
EXPECT_EQ(9, col);
EXPECT_EQ("'__off64_T' doesn't exist.", msg);
};
});
EXPECT_FALSE(parser.parse(source));
}
@ -981,12 +977,11 @@ typedef long __off64_t;
typedef __off64_t __loff_t;
typedef __off64_t __loff_t;
)";
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
EXPECT_EQ(4, line);
EXPECT_EQ(19, col);
EXPECT_EQ("'__loff_t' already exists.", msg);
};
});
EXPECT_FALSE(parser.parse(source));
}
}
@ -1034,12 +1029,11 @@ is_symbol <- < Name >
ref aaa
ref bbb
)";
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
EXPECT_EQ(3, line);
EXPECT_EQ(5, col);
EXPECT_EQ("'bbb' doesn't exist.", msg);
};
});
std::shared_ptr<Ast> ast;
dic.clear();
EXPECT_FALSE(parser.parse(source, ast));
@ -1050,13 +1044,12 @@ ref bbb
ref aaa
decl aaa
)";
parser.log = [](size_t line, size_t col, const std::string &msg,
const std::string & /*rule*/) {
parser.set_logger([](size_t line, size_t col, const std::string &msg) {
std::cerr << line << ":" << col << ": " << msg << "\n";
EXPECT_EQ(3, line);
EXPECT_EQ(6, col);
EXPECT_EQ("'aaa' already exists.", msg);
};
});
std::shared_ptr<Ast> ast;
dic.clear();
EXPECT_FALSE(parser.parse(source, ast));
@ -1452,12 +1445,11 @@ TEST(ErrorTest, Default_error_handling_1) {
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
EXPECT_FALSE(pg.parse(" @ aaa typo "));
EXPECT_EQ(i, errors.size());
@ -1479,12 +1471,11 @@ TEST(ErrorTest, Default_error_handling_2) {
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
EXPECT_FALSE(pg.parse(" @ aaa typo "));
EXPECT_EQ(i, errors.size());
@ -1524,12 +1515,11 @@ TEST(ErrorTest, Default_error_handling_fiblang) {
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
EXPECT_FALSE(pg.parse(R"(def fib(x)
x < 2 ? 1 : fib(x - 2) + fib(x - 1)
@ -1582,12 +1572,11 @@ entry <- (!(__ / HEADER) .)+ { error_message "invalid entry." }
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
pg.enable_ast();
@ -1647,12 +1636,11 @@ TEST(ErrorTest, Error_recovery_2) {
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
pg.enable_ast();
@ -1735,12 +1723,11 @@ skip_puncs <- [|=]* _
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
pg.enable_ast();
@ -1849,12 +1836,11 @@ SkipToRCUR ← (!RCUR (LCUR SkipToRCUR / .))* RCUR
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
pg.enable_ast();
@ -1899,12 +1885,11 @@ STR <- < [a-z0-9]+ >
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
};
});
EXPECT_FALSE(pg.parse(R"(1 = ah
2 = b
@ -2019,12 +2004,12 @@ expr <- 'hello'
};
size_t i = 0;
pg.log = [&](size_t ln, size_t col, const std::string &msg,
const std::string & /*rule*/) {
pg.set_logger([&](size_t ln, size_t col, const std::string &msg, const std::string &rule) {
std::stringstream ss;
ss << ln << ":" << col << ": " << msg;
EXPECT_EQ(errors[i++], ss.str());
EXPECT_EQ("unterminated_comment", rule);
EXPECT_EQ(4, locations.size());
EXPECT_EQ(1, locations[0].first);
EXPECT_EQ(1, locations[0].second);
@ -2034,7 +2019,7 @@ expr <- 'hello'
EXPECT_EQ(3, locations[2].second);
EXPECT_EQ(4, locations[3].first);
EXPECT_EQ(4, locations[3].second);
};
});
EXPECT_FALSE(pg.parse(R"(/* line 1:1 is the first comment open
/* line 2:2 is the second