diff --git a/peglib.h b/peglib.h index 98c41aa..a54fb2e 100644 --- a/peglib.h +++ b/peglib.h @@ -459,6 +459,9 @@ struct SemanticValues : protected std::vector return peg::line_info(ss, s_); } + // Choice count + size_t choice_count() const { return choice_count_; } + // Choice number (0 based index) size_t choice() const { return choice_; } @@ -480,7 +483,7 @@ struct SemanticValues : protected std::vector return this->transform(beg, end, [](const any& v) { return v.get(); }); } - SemanticValues() : s_(nullptr), n_(0), choice_(0) {} + SemanticValues() : s_(nullptr), n_(0), choice_count_(0), choice_(0) {} using std::vector::iterator; using std::vector::const_iterator; @@ -512,6 +515,7 @@ private: const char* s_; size_t n_; + size_t choice_count_; size_t choice_; template @@ -532,6 +536,17 @@ private: } return r; } + + void reset() { + path = nullptr; + ss = nullptr; + tokens.clear(); + + s_ = nullptr; + n_ = 0; + choice_count_ = 0; + choice_ = 0; + } }; /* @@ -846,11 +861,9 @@ public: if (!sv.empty()) { sv.clear(); } + sv.reset(); sv.path = path; sv.ss = s; - sv.s_ = nullptr; - sv.n_ = 0; - sv.tokens.clear(); return sv; } @@ -996,6 +1009,7 @@ public: } sv.s_ = chldsv.c_str(); sv.n_ = chldsv.length(); + sv.choice_count_ = opes_.size(); sv.choice_ = id; sv.tokens.insert(sv.tokens.end(), chldsv.tokens.begin(), chldsv.tokens.end()); @@ -2893,12 +2907,18 @@ inline constexpr unsigned int operator "" _(const char* s, size_t) { template struct AstBase : public Annotation { - AstBase(const char* a_path, size_t a_line, size_t a_column, const char* a_name, const std::vector>& a_nodes) + AstBase(const char* a_path, size_t a_line, size_t a_column, + const char* a_name, size_t a_choice_count, size_t a_choice, + const std::vector>& a_nodes) : path(a_path ? a_path : "") , line(a_line) , column(a_column) , name(a_name) + , choice_count(a_choice_count) + , choice(a_choice) , original_name(a_name) + , original_choice_count(a_choice_count) + , original_choice(a_choice) #ifndef PEGLIB_NO_CONSTEXPR_SUPPORT , tag(str2tag(a_name)) , original_tag(tag) @@ -2907,12 +2927,18 @@ struct AstBase : public Annotation , nodes(a_nodes) {} - AstBase(const char* a_path, size_t a_line, size_t a_column, const char* a_name, const std::string& a_token) + AstBase(const char* a_path, size_t a_line, size_t a_column, + const char* a_name, size_t a_choice_count, size_t a_choice, + const std::string& a_token) : path(a_path ? a_path : "") , line(a_line) , column(a_column) , name(a_name) + , choice_count(a_choice_count) + , choice(a_choice) , original_name(a_name) + , original_choice_count(a_choice_count) + , original_choice(a_choice) #ifndef PEGLIB_NO_CONSTEXPR_SUPPORT , tag(str2tag(a_name)) , original_tag(tag) @@ -2921,12 +2947,17 @@ struct AstBase : public Annotation , token(a_token) {} - AstBase(const AstBase& ast, const char* a_original_name) + AstBase(const AstBase& ast, const char* a_original_name, + size_t a_original_choice_count, size_t a_original_choise) : path(ast.path) , line(ast.line) , column(ast.column) , name(ast.name) + , choice_count(ast.choice_count) + , choice(ast.choice) , original_name(a_original_name) + , original_choice_count(a_original_choice_count) + , original_choice(a_original_choise) #ifndef PEGLIB_NO_CONSTEXPR_SUPPORT , tag(ast.tag) , original_tag(str2tag(a_original_name)) @@ -2942,7 +2973,11 @@ struct AstBase : public Annotation const size_t column; const std::string name; + const size_t choice_count; + const size_t choice; const std::string original_name; + const size_t original_choice_count; + const size_t original_choice; #ifndef PEGLIB_NO_CONSTEXPR_SUPPORT const unsigned int tag; const unsigned int original_tag; @@ -2966,11 +3001,12 @@ void ast_to_s_core( for (auto i = 0; i < level; i++) { s += " "; } - std::string name; - if (ast.name == ast.original_name) { - name = ast.name; - } else { - name = ast.original_name + "[" + ast.name + "]"; + auto name = ast.original_name; + if (ast.original_choice_count > 0) { + name += "/" + std::to_string(ast.original_choice); + } + if (ast.name != ast.original_name) { + name += "[" + ast.name + "]"; } if (ast.is_token) { s += "- " + name + " (" + ast.token + ")\n"; @@ -3009,7 +3045,8 @@ struct AstOptimizer if (opt && original->nodes.size() == 1) { auto child = optimize(original->nodes[0], parent); - return std::make_shared(*child, original->name.c_str()); + return std::make_shared( + *child, original->name.c_str(), original->choice_count, original->choice); } auto ast = std::make_shared(*original); @@ -3199,10 +3236,16 @@ public: auto line = line_info(sv.ss, sv.c_str()); if (rule.is_token()) { - return std::make_shared(sv.path, line.first, line.second, name.c_str(), sv.token()); + return std::make_shared( + sv.path, line.first, line.second, + name.c_str(), sv.choice_count(), sv.choice(), + sv.token()); } - auto ast = std::make_shared(sv.path, line.first, line.second, name.c_str(), sv.transform>()); + auto ast = std::make_shared( + sv.path, line.first, line.second, + name.c_str(), sv.choice_count(), sv.choice(), + sv.transform>()); for (auto node: ast->nodes) { node->parent = ast;