Error message support

This commit is contained in:
yhirose 2021-01-15 19:27:31 -05:00
parent 1442e3e21f
commit d4aa6e7df5

View File

@ -2251,7 +2251,6 @@ public:
std::function<void(const char *s, size_t n, size_t matchlen, std::any &value, std::function<void(const char *s, size_t n, size_t matchlen, std::any &value,
std::any &dt)> std::any &dt)>
leave; leave;
std::function<std::string()> error_message;
bool ignoreSemanticValue = false; bool ignoreSemanticValue = false;
std::shared_ptr<Ope> whitespaceOpe; std::shared_ptr<Ope> whitespaceOpe;
std::shared_ptr<Ope> wordOpe; std::shared_ptr<Ope> wordOpe;
@ -2262,6 +2261,8 @@ public:
TracerLeave tracer_leave; TracerLeave tracer_leave;
bool disable_action = false; bool disable_action = false;
std::string error_message;
private: private:
friend class Reference; friend class Reference;
friend class ParserGenerator; friend class ParserGenerator;
@ -2505,13 +2506,6 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &vs,
vs.emplace_back(std::move(val)); vs.emplace_back(std::move(val));
vs.tags.emplace_back(str2tag(outer_->name)); vs.tags.emplace_back(str2tag(outer_->name));
} }
} else {
if (outer_->error_message) {
if (c.error_info.message_pos < s) {
c.error_info.message_pos = s;
c.error_info.message = outer_->error_message();
}
}
} }
return len; return len;
@ -2688,7 +2682,16 @@ inline size_t Recovery::parse_core(const char *s, size_t n, SemanticValues &vs,
if (success(len)) { if (success(len)) {
c.recovered = true; c.recovered = true;
if (c.log) { c.error_info.output_log(c.log, c.s, c.l); } if (c.log) {
auto label = dynamic_cast<Reference *>(rule.args_[0].get());
if (label) {
if (!label->rule_->error_message.empty()) {
c.error_info.message_pos = c.error_info.error_pos;
c.error_info.message = label->rule_->error_message;
}
}
c.error_info.output_log(c.log, c.s, c.l);
}
} }
c.error_info.clear(); c.error_info.clear();
@ -3024,7 +3027,12 @@ private:
// Instruction grammars // Instruction grammars
g["Instruction"] <= g["Instruction"] <=
seq(g["BeginBlacket"], cho(g["PrecedenceClimbing"]), g["EndBlacket"]); seq(g["BeginBlacket"],
cho(
cho(g["PrecedenceClimbing"]),
cho(g["ErrorMessage"])
),
g["EndBlacket"]);
~g["SpacesZom"] <= zom(g["Space"]); ~g["SpacesZom"] <= zom(g["Space"]);
~g["SpacesOom"] <= oom(g["Space"]); ~g["SpacesOom"] <= oom(g["Space"]);
@ -3033,7 +3041,7 @@ private:
// PrecedenceClimbing instruction // PrecedenceClimbing instruction
g["PrecedenceClimbing"] <= g["PrecedenceClimbing"] <=
seq(lit("precedence"), g["SpacesZom"], g["PrecedenceInfo"], seq(lit("precedence"), g["SpacesOom"], g["PrecedenceInfo"],
zom(seq(g["SpacesOom"], g["PrecedenceInfo"])), g["SpacesZom"]); zom(seq(g["SpacesOom"], g["PrecedenceInfo"])), g["SpacesZom"]);
g["PrecedenceInfo"] <= g["PrecedenceInfo"] <=
seq(g["PrecedenceAssoc"], seq(g["PrecedenceAssoc"],
@ -3043,6 +3051,11 @@ private:
seq(npd(cho(g["PrecedenceAssoc"], g["Space"], chr('}'))), dot()))); seq(npd(cho(g["PrecedenceAssoc"], g["Space"], chr('}'))), dot())));
g["PrecedenceAssoc"] <= cls("LR"); g["PrecedenceAssoc"] <= cls("LR");
// Error message instruction
g["ErrorMessage"] <= seq(lit("message"), g["SpacesOom"],
g["LiteralD"],
g["SpacesZom"]);
// Set definition names // Set definition names
for (auto &x : g) { for (auto &x : g) {
x.second.name = x.first; x.second.name = x.first;
@ -3340,6 +3353,14 @@ private:
}; };
g["PrecedenceOpe"] = [](const SemanticValues &vs) { return vs.token(); }; g["PrecedenceOpe"] = [](const SemanticValues &vs) { return vs.token(); };
g["PrecedenceAssoc"] = [](const SemanticValues &vs) { return vs.token(); }; g["PrecedenceAssoc"] = [](const SemanticValues &vs) { return vs.token(); };
g["ErrorMessage"] = [](const SemanticValues &vs) {
Instruction instruction;
instruction.type = "message";
instruction.data = std::any_cast<std::string>(vs[0]);
return instruction;
};
} }
bool apply_precedence_instruction(Definition &rule, bool apply_precedence_instruction(Definition &rule,
@ -3554,6 +3575,8 @@ private:
if (!apply_precedence_instruction(rule, info, s, log)) { if (!apply_precedence_instruction(rule, info, s, log)) {
return nullptr; return nullptr;
} }
} else if (instruction.type == "message") {
rule.error_message = std::any_cast<std::string>(instruction.data);
} }
} }