@@ -379,24 +379,26 @@ class Trie {
379379public:
380380 Trie (const std::vector<std::string> &items, bool ignore_case)
381381 : ignore_case_(ignore_case) {
382+ size_t id = 0 ;
382383 for (const auto &item : items) {
383384 for (size_t len = 1 ; len <= item.size (); len++) {
384385 auto last = len == item.size ();
385386 const auto &s = ignore_case ? to_lower (item) : item;
386387 std::string_view sv (s.data (), len);
387388 auto it = dic_.find (sv);
388389 if (it == dic_.end ()) {
389- dic_.emplace (sv, Info{last, last});
390+ dic_.emplace (sv, Info{last, last, id });
390391 } else if (last) {
391392 it->second .match = true ;
392393 } else {
393394 it->second .done = false ;
394395 }
395396 }
397+ id++;
396398 }
397399 }
398400
399- size_t match (const char *text, size_t text_len) const {
401+ size_t match (const char *text, size_t text_len, size_t &id ) const {
400402 size_t match_len = 0 ;
401403 auto done = false ;
402404 size_t len = 1 ;
@@ -407,14 +409,19 @@ class Trie {
407409 if (it == dic_.end ()) {
408410 done = true ;
409411 } else {
410- if (it->second .match ) { match_len = len; }
412+ if (it->second .match ) {
413+ match_len = len;
414+ id = it->second .id ;
415+ }
411416 if (it->second .done ) { done = true ; }
412417 }
413418 len += 1 ;
414419 }
415420 return match_len;
416421 }
417422
423+ size_t size () const { return dic_.size (); }
424+
418425private:
419426 std::string to_lower (std::string s) const {
420427 for (char &c : s) {
@@ -426,6 +433,7 @@ class Trie {
426433 struct Info {
427434 bool done;
428435 bool match;
436+ size_t id;
429437 };
430438
431439 // TODO: Use unordered_map when heterogeneous lookup is supported in C++20
@@ -580,6 +588,7 @@ struct SemanticValues : protected std::vector<std::any> {
580588
581589private:
582590 friend class Context ;
591+ friend class Dictionary ;
583592 friend class Sequence ;
584593 friend class PrioritizedChoice ;
585594 friend class Repetition ;
@@ -2673,12 +2682,17 @@ inline size_t Ope::parse(const char *s, size_t n, SemanticValues &vs,
26732682inline size_t Dictionary::parse_core (const char *s, size_t n,
26742683 SemanticValues &vs, Context &c,
26752684 std::any &dt) const {
2676- auto i = trie_.match (s, n);
2685+ size_t id;
2686+ auto i = trie_.match (s, n, id);
2687+
26772688 if (i == 0 ) {
26782689 c.set_error_pos (s);
26792690 return static_cast <size_t >(-1 );
26802691 }
26812692
2693+ vs.choice_count_ = trie_.size ();
2694+ vs.choice_ = id;
2695+
26822696 // Word check
26832697 if (c.wordOpe ) {
26842698 auto save_ignore_trace_state = c.ignore_trace_state ;
@@ -2792,7 +2806,8 @@ inline size_t Holder::parse_core(const char *s, size_t n, SemanticValues &vs,
27922806 auto tok_ptr = dynamic_cast <const peg::TokenBoundary *>(ope_ptr);
27932807 if (tok_ptr) { ope_ptr = tok_ptr->ope_ .get (); }
27942808 }
2795- if (!dynamic_cast <const peg::PrioritizedChoice *>(ope_ptr)) {
2809+ if (!dynamic_cast <const peg::PrioritizedChoice *>(ope_ptr) &&
2810+ !dynamic_cast <const peg::Dictionary *>(ope_ptr)) {
27962811 chvs.choice_count_ = 0 ;
27972812 chvs.choice_ = 0 ;
27982813 }
0 commit comments