mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Fixed #202 again
This commit is contained in:
parent
0ada38acec
commit
959128ec0f
8
peglib.h
8
peglib.h
@ -662,6 +662,7 @@ struct ErrorInfo {
|
||||
const char *message_pos = nullptr;
|
||||
std::string message;
|
||||
mutable const char *last_output_pos = nullptr;
|
||||
bool keep_previous_token = false;
|
||||
|
||||
void clear() {
|
||||
error_pos = nullptr;
|
||||
@ -1047,9 +1048,11 @@ public:
|
||||
auto &chldsv = c.push();
|
||||
c.push_capture_scope();
|
||||
|
||||
c.error_info.keep_previous_token = id > 0;
|
||||
auto se = scope_exit([&]() {
|
||||
c.pop();
|
||||
c.pop_capture_scope();
|
||||
c.error_info.keep_previous_token = false;
|
||||
});
|
||||
|
||||
len = ope->parse(s, n, chldsv, c, dt);
|
||||
@ -1123,7 +1126,7 @@ public:
|
||||
auto se = scope_exit([&]() { c.pop_capture_scope(); });
|
||||
auto save_sv_size = vs.size();
|
||||
auto save_tok_size = vs.tokens.size();
|
||||
auto save_error_info = c.error_info;
|
||||
|
||||
const auto &rule = *ope_;
|
||||
auto len = rule.parse(s + i, n - i, vs, c, dt);
|
||||
if (success(len)) {
|
||||
@ -1138,7 +1141,6 @@ public:
|
||||
vs.tokens.erase(vs.tokens.begin() +
|
||||
static_cast<std::ptrdiff_t>(save_tok_size));
|
||||
}
|
||||
c.error_info = save_error_info;
|
||||
break;
|
||||
}
|
||||
i += len;
|
||||
@ -2539,7 +2541,7 @@ inline const std::vector<size_t> &SemanticValues::source_line_index() const {
|
||||
inline void Context::set_error_pos(const char *a_s, const char *literal) {
|
||||
if (log) {
|
||||
if (error_info.error_pos <= a_s) {
|
||||
if (error_info.error_pos < a_s) {
|
||||
if (error_info.error_pos < a_s || !error_info.keep_previous_token) {
|
||||
error_info.error_pos = a_s;
|
||||
error_info.expected_tokens.clear();
|
||||
}
|
||||
|
@ -1248,6 +1248,54 @@ TEST(ErrorTest, Default_error_handling_2) {
|
||||
EXPECT_FALSE(pg.parse(" @ aaa typo "));
|
||||
}
|
||||
|
||||
TEST(ErrorTest, Default_error_handling_fiblang) {
|
||||
parser pg(R"(
|
||||
# Syntax
|
||||
START ← STATEMENTS
|
||||
STATEMENTS ← (DEFINITION / EXPRESSION)*
|
||||
DEFINITION ← 'def' ↑ Identifier '(' Identifier ')' EXPRESSION
|
||||
EXPRESSION ← TERNARY
|
||||
TERNARY ← CONDITION ('?' EXPRESSION (':' / %recover(col)) EXPRESSION)?
|
||||
CONDITION ← INFIX (ConditionOperator INFIX)?
|
||||
INFIX ← CALL (InfixOperator CALL)*
|
||||
CALL ← PRIMARY ('(' EXPRESSION ')')?
|
||||
PRIMARY ← FOR / Identifier / '(' ↑ EXPRESSION ')' / Number
|
||||
FOR ← 'for' ↑ Identifier 'from' Number 'to' Number EXPRESSION
|
||||
|
||||
# Token
|
||||
ConditionOperator ← '<'
|
||||
InfixOperator ← '+' / '-'
|
||||
Identifier ← !Keyword < [a-zA-Z][a-zA-Z0-9_]* >
|
||||
Number ← < [0-9]+ >
|
||||
Keyword ← 'def' / 'for' / 'from' / 'to'
|
||||
|
||||
%whitespace ← [ \t\r\n]*
|
||||
%word ← [a-zA-Z]
|
||||
|
||||
col ← '' { message "missing colon." }
|
||||
)");
|
||||
|
||||
EXPECT_TRUE(!!pg);
|
||||
|
||||
std::vector<std::string> errors{
|
||||
R"(4:7: syntax error, unexpected 'frm', expecting 'from'.)",
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
pg.log = [&](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)
|
||||
|
||||
for n frm 1 to 30
|
||||
puts(fib(n))
|
||||
)"));
|
||||
}
|
||||
|
||||
TEST(ErrorTest, Error_recovery_1) {
|
||||
parser pg(R"(
|
||||
START <- __? SECTION*
|
||||
@ -1395,7 +1443,7 @@ TEST(ErrorTest, Error_recovery_2) {
|
||||
R"(1:38: syntax error, unexpected 'ddd', expecting '"', <NUM>.)",
|
||||
R"(1:55: syntax error, unexpected ']', expecting '"'.)",
|
||||
R"(1:58: syntax error, unexpected '\n', expecting '"', <NUM>.)",
|
||||
R"(2:3: syntax error.)",
|
||||
R"(2:3: syntax error, expecting ']'.)",
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user