Allow more than one instruction

This commit is contained in:
yhirose 2022-04-02 08:10:39 -04:00
parent b85606ce2e
commit 82fd01f3d1

115
peglib.h
View File

@ -463,7 +463,7 @@ class Context;
struct SemanticValues : protected std::vector<std::any> { struct SemanticValues : protected std::vector<std::any> {
SemanticValues() = default; SemanticValues() = default;
SemanticValues(Context *c): c_(c) {} SemanticValues(Context *c) : c_(c) {}
// Input text // Input text
const char *path = nullptr; const char *path = nullptr;
@ -569,7 +569,7 @@ private:
/* /*
* Semantic action * Semantic action
*/ */
template <typename F, typename... Args> std::any call(F fn, Args &&... args) { template <typename F, typename... Args> std::any call(F fn, Args &&...args) {
using R = decltype(fn(std::forward<Args>(args)...)); using R = decltype(fn(std::forward<Args>(args)...));
if constexpr (std::is_void<R>::value) { if constexpr (std::is_void<R>::value) {
fn(std::forward<Args>(args)...); fn(std::forward<Args>(args)...);
@ -975,7 +975,7 @@ public:
class Sequence : public Ope { class Sequence : public Ope {
public: public:
template <typename... Args> template <typename... Args>
Sequence(const Args &... args) Sequence(const Args &...args)
: opes_{static_cast<std::shared_ptr<Ope>>(args)...} {} : opes_{static_cast<std::shared_ptr<Ope>>(args)...} {}
Sequence(const std::vector<std::shared_ptr<Ope>> &opes) : opes_(opes) {} Sequence(const std::vector<std::shared_ptr<Ope>> &opes) : opes_(opes) {}
Sequence(std::vector<std::shared_ptr<Ope>> &&opes) : opes_(opes) {} Sequence(std::vector<std::shared_ptr<Ope>> &&opes) : opes_(opes) {}
@ -1018,7 +1018,7 @@ public:
class PrioritizedChoice : public Ope { class PrioritizedChoice : public Ope {
public: public:
template <typename... Args> template <typename... Args>
PrioritizedChoice(bool for_label, const Args &... args) PrioritizedChoice(bool for_label, const Args &...args)
: opes_{static_cast<std::shared_ptr<Ope>>(args)...}, : opes_{static_cast<std::shared_ptr<Ope>>(args)...},
for_label_(for_label) {} for_label_(for_label) {}
PrioritizedChoice(const std::vector<std::shared_ptr<Ope>> &opes) PrioritizedChoice(const std::vector<std::shared_ptr<Ope>> &opes)
@ -1576,16 +1576,16 @@ public:
/* /*
* Factories * Factories
*/ */
template <typename... Args> std::shared_ptr<Ope> seq(Args &&... args) { template <typename... Args> std::shared_ptr<Ope> seq(Args &&...args) {
return std::make_shared<Sequence>(static_cast<std::shared_ptr<Ope>>(args)...); return std::make_shared<Sequence>(static_cast<std::shared_ptr<Ope>>(args)...);
} }
template <typename... Args> std::shared_ptr<Ope> cho(Args &&... args) { template <typename... Args> std::shared_ptr<Ope> cho(Args &&...args) {
return std::make_shared<PrioritizedChoice>( return std::make_shared<PrioritizedChoice>(
false, static_cast<std::shared_ptr<Ope>>(args)...); false, static_cast<std::shared_ptr<Ope>>(args)...);
} }
template <typename... Args> std::shared_ptr<Ope> cho4label_(Args &&... args) { template <typename... Args> std::shared_ptr<Ope> cho4label_(Args &&...args) {
return std::make_shared<PrioritizedChoice>( return std::make_shared<PrioritizedChoice>(
true, static_cast<std::shared_ptr<Ope>>(args)...); true, static_cast<std::shared_ptr<Ope>>(args)...);
} }
@ -2467,9 +2467,7 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs,
} }
inline const std::vector<size_t> &SemanticValues::source_line_index() const { inline const std::vector<size_t> &SemanticValues::source_line_index() const {
if (!c_) { if (!c_) { std::vector<size_t>(); }
std::vector<size_t>();
}
if (c_->source_line_index.empty()) { if (c_->source_line_index.empty()) {
for (size_t pos = 0; pos < c_->l; pos++) { for (size_t pos = 0; pos < c_->l; pos++) {
if (c_->s[pos] == '\n') { c_->source_line_index.push_back(pos); } if (c_->s[pos] == '\n') { c_->source_line_index.push_back(pos); }
@ -3058,14 +3056,16 @@ private:
struct Instruction { struct Instruction {
std::string type; std::string type;
std::any data; std::any data;
std::string_view sv;
}; };
struct Data { struct Data {
std::shared_ptr<Grammar> grammar; std::shared_ptr<Grammar> grammar;
std::string start; std::string start;
const char *start_pos = nullptr; const char *start_pos = nullptr;
std::vector<std::pair<std::string, const char *>> duplicates; std::vector<std::pair<std::string, const char *>> duplicates_of_definition;
std::map<std::string, Instruction> instructions; std::vector<std::pair<std::string, const char *>> duplicates_of_instruction;
std::map<std::string, std::vector<Instruction>> instructions;
std::set<std::string_view> captures; std::set<std::string_view> captures;
bool enablePackratParsing = true; bool enablePackratParsing = true;
@ -3194,10 +3194,14 @@ private:
~g["COMMA"] <= seq(chr(','), g["Spacing"]); ~g["COMMA"] <= seq(chr(','), g["Spacing"]);
// Instruction grammars // Instruction grammars
g["Instruction"] <= seq(g["BeginBlacket"], g["Instruction"] <=
cho(cho(g["PrecedenceClimbing"]), seq(g["BeginBlacket"],
cho(g["ErrorMessage"]), cho(g["NoAstOpt"])), opt(seq(g["InstructionItem"], zom(seq(g["InstructionItemSeparator"],
g["EndBlacket"]); g["InstructionItem"])))),
g["EndBlacket"]);
g["InstructionItem"] <=
cho(g["PrecedenceClimbing"], g["ErrorMessage"], g["NoAstOpt"]);
~g["InstructionItemSeparator"] <= seq(chr(';'), g["Spacing"]);
~g["SpacesZom"] <= zom(g["Space"]); ~g["SpacesZom"] <= zom(g["Space"]);
~g["SpacesOom"] <= oom(g["Space"]); ~g["SpacesOom"] <= oom(g["Space"]);
@ -3245,16 +3249,34 @@ private:
std::vector<std::string> params; std::vector<std::string> params;
std::shared_ptr<Ope> ope; std::shared_ptr<Ope> ope;
auto has_instructions = false;
if (is_macro) { if (is_macro) {
params = std::any_cast<std::vector<std::string>>(vs[2]); params = std::any_cast<std::vector<std::string>>(vs[2]);
ope = std::any_cast<std::shared_ptr<Ope>>(vs[4]); ope = std::any_cast<std::shared_ptr<Ope>>(vs[4]);
if (vs.size() == 6) { if (vs.size() == 6) {
data.instructions[name] = std::any_cast<Instruction>(vs[5]); has_instructions = true;
} }
} else { } else {
ope = std::any_cast<std::shared_ptr<Ope>>(vs[3]); ope = std::any_cast<std::shared_ptr<Ope>>(vs[3]);
if (vs.size() == 5) { if (vs.size() == 5) {
data.instructions[name] = std::any_cast<Instruction>(vs[4]); has_instructions = true;
}
}
if (has_instructions) {
auto index = is_macro ? 5 : 4;
std::set<std::string> types;
for (const auto &instruction :
std::any_cast<std::vector<Instruction>>(vs[index])) {
const auto &type = instruction.type;
if (types.find(type) == types.end()) {
data.instructions[name].push_back(instruction);
types.insert(instruction.type);
} else {
// data.duplicates_of_instruction.emplace_back(type, vs.sv().data());
data.duplicates_of_instruction.emplace_back(type, instruction.sv.data());
}
} }
} }
@ -3273,7 +3295,7 @@ private:
data.start_pos = vs.sv().data(); data.start_pos = vs.sv().data();
} }
} else { } else {
data.duplicates.emplace_back(name, vs.sv().data()); data.duplicates_of_definition.emplace_back(name, vs.sv().data());
} }
}; };
@ -3548,6 +3570,7 @@ private:
Instruction instruction; Instruction instruction;
instruction.type = "precedence"; instruction.type = "precedence";
instruction.data = binOpeInfo; instruction.data = binOpeInfo;
instruction.sv = vs.sv();
return instruction; return instruction;
}; };
g["PrecedenceInfo"] = [](const SemanticValues &vs) { g["PrecedenceInfo"] = [](const SemanticValues &vs) {
@ -3560,14 +3583,20 @@ private:
Instruction instruction; Instruction instruction;
instruction.type = "message"; instruction.type = "message";
instruction.data = std::any_cast<std::string>(vs[0]); instruction.data = std::any_cast<std::string>(vs[0]);
instruction.sv = vs.sv();
return instruction; return instruction;
}; };
g["NoAstOpt"] = [](const SemanticValues & /*vs*/) { g["NoAstOpt"] = [](const SemanticValues & vs) {
Instruction instruction; Instruction instruction;
instruction.type = "no_ast_opt"; instruction.type = "no_ast_opt";
instruction.sv = vs.sv();
return instruction; return instruction;
}; };
g["Instruction"] = [](const SemanticValues &vs) {
return vs.transform<Instruction>();
};
} }
bool apply_precedence_instruction(Definition &rule, bool apply_precedence_instruction(Definition &rule,
@ -3662,13 +3691,27 @@ private:
} }
// Check duplicated definitions // Check duplicated definitions
auto ret = data.duplicates.empty(); auto ret = true;
for (const auto &[name, ptr] : data.duplicates) { if (!data.duplicates_of_definition.empty()) {
if (log) { for (const auto &[name, ptr] : data.duplicates_of_definition) {
auto line = line_info(s, ptr); if (log) {
log(line.first, line.second, "'" + name + "' is already defined."); auto line = line_info(s, ptr);
log(line.first, line.second, "The definition '" + name + "' is already defined.");
}
} }
ret = false;
}
// Check duplicated instructions
if (!data.duplicates_of_instruction.empty()) {
for (const auto &[type, ptr] : data.duplicates_of_instruction) {
if (log) {
auto line = line_info(s, ptr);
log(line.first, line.second, "The instruction '" + type + "' is already defined.");
}
}
ret = false;
} }
// Set root definition // Set root definition
@ -3778,20 +3821,22 @@ private:
} }
// Apply instructions // Apply instructions
for (const auto &[name, instruction] : data.instructions) { for (const auto &[name, instructions] : data.instructions) {
auto &rule = grammar[name]; auto &rule = grammar[name];
if (instruction.type == "precedence") { for (const auto& instruction: instructions) {
const auto &info = if (instruction.type == "precedence") {
std::any_cast<PrecedenceClimbing::BinOpeInfo>(instruction.data); const auto &info =
std::any_cast<PrecedenceClimbing::BinOpeInfo>(instruction.data);
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);
} else if (instruction.type == "no_ast_opt") {
rule.no_ast_opt = true;
} }
} else if (instruction.type == "message") {
rule.error_message = std::any_cast<std::string>(instruction.data);
} else if (instruction.type == "no_ast_opt") {
rule.no_ast_opt = true;
} }
} }