mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +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;
|
const char *message_pos = nullptr;
|
||||||
std::string message;
|
std::string message;
|
||||||
mutable const char *last_output_pos = nullptr;
|
mutable const char *last_output_pos = nullptr;
|
||||||
|
bool keep_previous_token = false;
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
error_pos = nullptr;
|
error_pos = nullptr;
|
||||||
@ -1047,9 +1048,11 @@ public:
|
|||||||
auto &chldsv = c.push();
|
auto &chldsv = c.push();
|
||||||
c.push_capture_scope();
|
c.push_capture_scope();
|
||||||
|
|
||||||
|
c.error_info.keep_previous_token = id > 0;
|
||||||
auto se = scope_exit([&]() {
|
auto se = scope_exit([&]() {
|
||||||
c.pop();
|
c.pop();
|
||||||
c.pop_capture_scope();
|
c.pop_capture_scope();
|
||||||
|
c.error_info.keep_previous_token = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
len = ope->parse(s, n, chldsv, c, dt);
|
len = ope->parse(s, n, chldsv, c, dt);
|
||||||
@ -1123,7 +1126,7 @@ public:
|
|||||||
auto se = scope_exit([&]() { c.pop_capture_scope(); });
|
auto se = scope_exit([&]() { c.pop_capture_scope(); });
|
||||||
auto save_sv_size = vs.size();
|
auto save_sv_size = vs.size();
|
||||||
auto save_tok_size = vs.tokens.size();
|
auto save_tok_size = vs.tokens.size();
|
||||||
auto save_error_info = c.error_info;
|
|
||||||
const auto &rule = *ope_;
|
const auto &rule = *ope_;
|
||||||
auto len = rule.parse(s + i, n - i, vs, c, dt);
|
auto len = rule.parse(s + i, n - i, vs, c, dt);
|
||||||
if (success(len)) {
|
if (success(len)) {
|
||||||
@ -1138,7 +1141,6 @@ public:
|
|||||||
vs.tokens.erase(vs.tokens.begin() +
|
vs.tokens.erase(vs.tokens.begin() +
|
||||||
static_cast<std::ptrdiff_t>(save_tok_size));
|
static_cast<std::ptrdiff_t>(save_tok_size));
|
||||||
}
|
}
|
||||||
c.error_info = save_error_info;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i += len;
|
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) {
|
inline void Context::set_error_pos(const char *a_s, const char *literal) {
|
||||||
if (log) {
|
if (log) {
|
||||||
if (error_info.error_pos <= a_s) {
|
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.error_pos = a_s;
|
||||||
error_info.expected_tokens.clear();
|
error_info.expected_tokens.clear();
|
||||||
}
|
}
|
||||||
|
@ -1248,6 +1248,54 @@ TEST(ErrorTest, Default_error_handling_2) {
|
|||||||
EXPECT_FALSE(pg.parse(" @ aaa typo "));
|
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) {
|
TEST(ErrorTest, Error_recovery_1) {
|
||||||
parser pg(R"(
|
parser pg(R"(
|
||||||
START <- __? SECTION*
|
START <- __? SECTION*
|
||||||
@ -1395,7 +1443,7 @@ TEST(ErrorTest, Error_recovery_2) {
|
|||||||
R"(1:38: syntax error, unexpected 'ddd', expecting '"', <NUM>.)",
|
R"(1:38: syntax error, unexpected 'ddd', expecting '"', <NUM>.)",
|
||||||
R"(1:55: syntax error, unexpected ']', expecting '"'.)",
|
R"(1:55: syntax error, unexpected ']', expecting '"'.)",
|
||||||
R"(1:58: syntax error, unexpected '\n', expecting '"', <NUM>.)",
|
R"(1:58: syntax error, unexpected '\n', expecting '"', <NUM>.)",
|
||||||
R"(2:3: syntax error.)",
|
R"(2:3: syntax error, expecting ']'.)",
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user