mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Added set_logger
This commit is contained in:
parent
e5be920106
commit
66e5412b14
16
README.md
16
README.md
@ -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
|
||||
--------------------
|
||||
|
||||
|
@ -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 += "]";
|
||||
|
BIN
docs/native.wasm
BIN
docs/native.wasm
Binary file not shown.
@ -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(); }
|
||||
|
||||
|
30
peglib.h
30
peglib.h
@ -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_;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user