bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/7] conflicts: switch to partial order precedence system


From: Valentin Tolmer
Subject: [PATCH 2/7] conflicts: switch to partial order precedence system
Date: Thu, 1 Aug 2013 16:04:50 +0200

Even though it is not yet fully deployed, this commit lays the ground for
the partial order precedence system, by changing to a graph-based order and
introducing precedence groups (only the default one can be used for now).

* src/symtab.h (struct symbol): Removed extra fields
* src/symtab.h: New function declarations
* src/symtab.c: New functions for precedence and groups, new hash table for
groups
* src/AnnotationList.c, src/conflicts.c, src/gram.c, src/print-xml.c,
* src/symtab.c: Adaptation to the new prec_node structure
* tests/existing.at (GAWK LALR): Fix
---
 src/AnnotationList.c |    4 +-
 src/conflicts.c      |  133 +++++++++-------
 src/gram.c           |    4 +-
 src/print-xml.c      |    3 +-
 src/symtab.c         |  431 ++++++++++++++++++++++++++++++++++++++++++++++++--
 src/symtab.h         |   24 ++-
 tests/existing.at    |    8 +-
 7 files changed, 528 insertions(+), 79 deletions(-)

diff --git a/src/AnnotationList.c b/src/AnnotationList.c
index 9f0adb9..b1cfab1 100644
--- a/src/AnnotationList.c
+++ b/src/AnnotationList.c
@@ -740,7 +740,7 @@ AnnotationList__computeDominantContribution (AnnotationList 
const *self,
             if (reduce_precedence
                 && (reduce_precedence < shift_precedence
                     || (reduce_precedence == shift_precedence
-                        && token->content->assoc == right_assoc)))
+                        && token->content->prec_node->assoc == right_assoc)))
               continue;
             if (!AnnotationList__stateMakesContribution (self, nitems, ci,
                                                          lookaheads))
@@ -748,7 +748,7 @@ AnnotationList__computeDominantContribution (AnnotationList 
const *self,
             /* This uneliminated reduction contributes, so see if it can cause
                an error action.  */
             if (reduce_precedence == shift_precedence
-                 && token->content->assoc == non_assoc)
+                 && token->content->prec_node->assoc == non_assoc)
               {
                 /* It's not possible to find split-stable domination over
                    shift after a potential %nonassoc.  */
diff --git a/src/conflicts.c b/src/conflicts.c
index 30a2cab..b8f1dcc 100644
--- a/src/conflicts.c
+++ b/src/conflicts.c
@@ -53,7 +53,8 @@ enum conflict_resolution
     reduce_resolution,
     left_resolution,
     right_resolution,
-    nonassoc_resolution
+    nonassoc_resolution,
+    uncomparable_resolution
   };
 
 
@@ -90,6 +91,7 @@ log_resolution (rule *r, symbol_number token,
           break;
 
         case nonassoc_resolution:
+        case uncomparable_resolution:
           obstack_printf (&solved_conflicts_obstack,
                           _("    Conflict between rule %d and token %s"
                             " resolved as an error"),
@@ -132,6 +134,12 @@ log_resolution (rule *r, symbol_number token,
                           " (%%nonassoc %s)",
                           symbols[token]->tag);
           break;
+        case uncomparable_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          " (%s uncomparable with %s)",
+                          r->prec->symbol->tag,
+                          symbols[token]->tag);
+          break;
         }
 
       obstack_sgrow (&solved_conflicts_obstack, ".\n");
@@ -161,6 +169,7 @@ log_resolution (rule *r, symbol_number token,
                           xml_escape (symbols[token]->tag));
           break;
 
+        case uncomparable_resolution:
         case nonassoc_resolution:
           obstack_printf (&solved_conflicts_xml_obstack,
                           "        <resolution rule=\"%d\" symbol=\"%s\""
@@ -203,7 +212,13 @@ log_resolution (rule *r, symbol_number token,
           obstack_printf (&solved_conflicts_xml_obstack,
                           "%%nonassoc %s",
                           xml_escape (symbols[token]->tag));
-      break;
+          break;
+        case uncomparable_resolution:
+          obstack_printf (&solved_conflicts_xml_obstack,
+                          "%s uncomparable with %s",
+                          xml_escape_n (0, symbols[token]->tag),
+                          xml_escape_n (1, r->prec->symbol->tag));
+          break;
         }
 
       obstack_sgrow (&solved_conflicts_xml_obstack, "</resolution>\n");
@@ -243,7 +258,6 @@ flush_reduce (bitset lookahead_tokens, int token)
   bitset_reset (lookahead_tokens, token);
 }
 
-
 /*------------------------------------------------------------------.
 | Attempt to resolve shift-reduce conflict for one rule by means of |
 | precedence declarations.  It has already been checked that the    |
@@ -263,66 +277,73 @@ resolve_sr_conflict (state *s, int ruleno, symbol 
**errors, int *nerrs)
   reductions *reds = s->reductions;
   /* Find the rule to reduce by to get precedence of reduction.  */
   rule *redrule = reds->rules[ruleno];
-  int redprec = redrule->prec->prec;
+  prec_node *redprecsym = redrule->prec->prec_node;
   bitset lookahead_tokens = reds->lookahead_tokens[ruleno];
 
   for (i = 0; i < ntokens; i++)
     if (bitset_test (lookahead_tokens, i)
-        && bitset_test (lookahead_set, i)
-        && symbols[i]->content->prec)
+        && bitset_test (lookahead_set, i))
       {
-        /* Shift-reduce conflict occurs for token number i
-           and it has a precedence.
-           The precedence of shifting is that of token i.  */
-        if (symbols[i]->content->prec < redprec)
-          {
-            register_precedence (redrule->prec->number, i);
-            log_resolution (redrule, i, reduce_resolution);
-            flush_shift (s, i);
-          }
-        else if (symbols[i]->content->prec > redprec)
+        if (redprecsym && symbols[i]->content->prec_node)
           {
-            register_precedence (i, redrule->prec->number);
-            log_resolution (redrule, i, shift_resolution);
-            flush_reduce (lookahead_tokens, i);
+            /* Shift-reduce conflict occurs for token number i
+               and it has a precedence.
+               The precedence of shifting is that of token i.  */
+            if (is_prec_superior (redprecsym, symbols[i]->content->prec_node))
+              {
+                register_precedence (redrule->prec->number, i);
+                log_resolution (redrule, i, reduce_resolution);
+                flush_shift (s, i);
+              }
+            else if (is_prec_superior (symbols[i]->content->prec_node,
+                                       redprecsym))
+              {
+                register_precedence (i, redrule->prec->number);
+                log_resolution (redrule, i, shift_resolution);
+                flush_reduce (lookahead_tokens, i);
+              }
+            else if (is_prec_equal (redprecsym, 
symbols[i]->content->prec_node))
+              /* Matching precedence levels.
+                 For non-defined associativity, keep both: unexpected
+                 associativity conflict.
+                 For left associativity, keep only the reduction.
+                 For right associativity, keep only the shift.
+                 For nonassociativity, keep neither.  */
+
+              switch (symbols[i]->content->prec_node->assoc)
+                {
+                case undef_assoc:
+                  break;
+
+                case precedence_assoc:
+                  break;
+
+                case right_assoc:
+                  register_assoc (i, redrule->prec->number);
+                  log_resolution (redrule, i, right_resolution);
+                  flush_reduce (lookahead_tokens, i);
+                  break;
+
+                case left_assoc:
+                  register_assoc (i, redrule->prec->number);
+                  log_resolution (redrule, i, left_resolution);
+                  flush_shift (s, i);
+                  break;
+
+                case non_assoc:
+                  register_assoc (i, redrule->prec->number);
+                  log_resolution (redrule, i, nonassoc_resolution);
+                  flush_shift (s, i);
+                  flush_reduce (lookahead_tokens, i);
+                  /* Record an explicit error for this token.  */
+                  errors[(*nerrs)++] = symbols[i];
+                  break;
+                }
+            else
+              log_resolution (redrule, i, uncomparable_resolution);
           }
         else
-          /* Matching precedence levels.
-             For non-defined associativity, keep both: unexpected
-             associativity conflict.
-             For left associativity, keep only the reduction.
-             For right associativity, keep only the shift.
-             For nonassociativity, keep neither.  */
-
-          switch (symbols[i]->content->assoc)
-            {
-            case undef_assoc:
-              abort ();
-
-            case precedence_assoc:
-              break;
-
-            case right_assoc:
-              register_assoc (i, redrule->prec->number);
-              log_resolution (redrule, i, right_resolution);
-              flush_reduce (lookahead_tokens, i);
-              break;
-
-            case left_assoc:
-              register_assoc (i, redrule->prec->number);
-              log_resolution (redrule, i, left_resolution);
-              flush_shift (s, i);
-              break;
-
-            case non_assoc:
-              register_assoc (i, redrule->prec->number);
-              log_resolution (redrule, i, nonassoc_resolution);
-              flush_shift (s, i);
-              flush_reduce (lookahead_tokens, i);
-              /* Record an explicit error for this token.  */
-              errors[(*nerrs)++] = symbols[i];
-              break;
-            }
+          log_resolution (redrule, i, uncomparable_resolution);
       }
 }
 
@@ -354,7 +375,7 @@ set_conflicts (state *s, symbol **errors)
      check for shift-reduce conflict, and try to resolve using
      precedence.  */
   for (i = 0; i < reds->num; ++i)
-    if (reds->rules[i]->prec && reds->rules[i]->prec->prec
+    if (reds->rules[i]->prec /* && reds->rules[i]->prec->prec */
         && !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
       resolve_sr_conflict (s, i, errors, &nerrs);
 
diff --git a/src/gram.c b/src/gram.c
index 790ec3a..66f550c 100644
--- a/src/gram.c
+++ b/src/gram.c
@@ -239,7 +239,7 @@ grammar_dump (FILE *out, const char *title)
     for (i = ntokens; i < nsyms; i++)
       fprintf (out, "%5d  %5d   %5d  %s\n",
                i,
-               symbols[i]->content->prec, symbols[i]->content->assoc,
+               symbols[i]->content->prec, 
symbols[i]->content->prec_node->assoc,
                symbols[i]->tag);
     fprintf (out, "\n\n");
   }
@@ -262,7 +262,7 @@ grammar_dump (FILE *out, const char *title)
         fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u)   %2d ->",
                  i,
                  rule_i->prec ? rule_i->prec->prec : 0,
-                 rule_i->prec ? rule_i->prec->assoc : 0,
+                 rule_i->prec ? rule_i->prec->prec_node->assoc : 0,
                  rule_i->useful,
                  rhs_itemno,
                  rhs_itemno + rhs_count - 1,
diff --git a/src/print-xml.c b/src/print-xml.c
index 3ddaeba..60eaf36 100644
--- a/src/print-xml.c
+++ b/src/print-xml.c
@@ -392,7 +392,8 @@ print_grammar (FILE *out, int level)
       {
         char const *tag = symbols[token_translations[i]]->tag;
         int precedence = symbols[token_translations[i]]->content->prec;
-        assoc associativity = symbols[token_translations[i]]->content->assoc;
+        assoc associativity = 
symbols[token_translations[i]]->content->prec_node
+          ->assoc;
         xml_indent (out, level + 2);
         fprintf (out,
                  "<terminal symbol-number=\"%d\" token-number=\"%d\""
diff --git a/src/symtab.c b/src/symtab.c
index f6761c4..aa7c5e8 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -26,6 +26,7 @@
 #include "complain.h"
 #include "gram.h"
 #include "symtab.h"
+#include "symlist.h"
 
 /*-------------------------------------------------------------------.
 | Symbols sorted by tag.  Allocated by the first invocation of       |
@@ -58,6 +59,256 @@ static symgraph **prec_nodes;
 
 bool *used_assoc = NULL;
 
+/*-------------------------------------------------------------.
+| The current precedence group of symbols. Used by the parser. |
+`-------------------------------------------------------------*/
+
+static symgroup *current_group = NULL;
+
+/*-------------------------------------------------------.
+| The list of symbols declared in the current statement. |
+`-------------------------------------------------------*/
+
+static symbol_list *current_prec_declaration = NULL;
+
+/*-------------------------------------------------.
+| A counter to distinguish precedence declarations |
+`-------------------------------------------------*/
+
+static int current_prec_level = 0;
+
+/*-----------------------------.
+| Constructor for a prec_link. |
+`-----------------------------*/
+
+static prec_link *
+prec_link_new (prec_node *to, bool transitive)
+{
+  prec_link *res = malloc (sizeof *res);
+  res->target = to;
+  res->transitive = transitive;
+  res->next = NULL;
+  return res;
+}
+
+/*-------------------------------------.
+| Destructor for a simple symbol list. |
+`-------------------------------------*/
+
+static void
+symbol_list_prec_free (symbol_list *l)
+{
+  if (l)
+    {
+      symbol_list_prec_free (l->next);
+      free (l);
+    }
+}
+
+/*------------------------------------------------.
+| Check if PARENT has a higher priority than SON. |
+`------------------------------------------------*/
+
+bool
+is_prec_superior (prec_node *parent, prec_node *son)
+{
+  prec_link *l;
+  for (l = parent->sons; l; l = l->next)
+    if (l->target == son)
+      return true;
+  return false;
+}
+
+/*-----------------------------------------.
+| Check if S1 has the same priority as S2. |
+`-----------------------------------------*/
+
+bool
+is_prec_equal (prec_node *s1, prec_node *s2)
+{
+  prec_link *l;
+  if (s1 == s2)
+    return true;
+  for (l = s1->equals; l; l = l->next)
+    if (l->target == s2)
+      return true;
+  return false;
+}
+
+static inline void
+complain_contradicting_prec (location *loc, uniqstr s1, uniqstr s2, char c1,
+                             char c2)
+{
+  complain (loc, Wprecedence, _("contradicting declaration: %s %c %s is in "
+            "conflict with the previous declaration: %s %c %s"), s1, c1, s2,
+            s1, c2, s2);
+}
+
+/*-----------------------------------------------------------------------.
+| Compare LINK with TARGET, and return whether they are equal.           |
+| In case of equality, complain of the duplicate precedence declaration. |
+`-----------------------------------------------------------------------*/
+
+static inline bool
+is_prec_target (prec_node *l, prec_node *target, uniqstr from, char c,
+                location loc)
+{
+  if (l == target)
+    {
+      complain (&loc, Wprecedence, _("duplicate declaration of the precedence "
+                                     "relationship %s %c %s"), from, c,
+                target->symbol->tag);
+      return true;
+    }
+  return false;
+}
+
+/*-----------------------------------------.
+| Add a precedence relationship FROM > TO. |
+`-----------------------------------------*/
+
+static void
+add_prec_link (prec_node *from, prec_node *to, bool transitive, location loc)
+{
+  if (is_prec_superior (to, from))
+    complain_contradicting_prec(&loc, from->symbol->tag, to->symbol->tag,
+                                '>', '<');
+  else if (is_prec_equal (from, to))
+    complain_contradicting_prec(&loc, from->symbol->tag, to->symbol->tag,
+                                '>', '=');
+  else
+    {
+      if (from->sons)
+        {
+          if (is_prec_target (from->sons->target, to, from->symbol->tag, '>',
+                              loc))
+            return;
+
+          prec_link *son = from->sons;
+          for (; son->next; son = son->next)
+            if (is_prec_target (son->next->target, to, from->symbol->tag, '>',
+                                loc))
+              return;
+          son->next = prec_link_new (to, transitive);
+        }
+      else
+        from->sons = prec_link_new (to, transitive);
+    }
+}
+
+/*-------------------------------------------------.
+| Add a precedence relationship S1 == S2, one way. |
+`-------------------------------------------------*/
+
+static void
+create_prec_equal_link (prec_node *s1, prec_node *s2, bool transitive,
+                        location loc)
+{
+  if (s1->equals)
+    {
+            if (is_prec_target (s1->equals->target, s2, s1->symbol->tag, '=',
+                                loc))
+              return;
+      prec_link *eq = s1->equals;
+      for (; eq->next; eq = eq->next)
+            if (is_prec_target (eq->next->target, s2, s1->symbol->tag, '=',
+                                loc))
+              return;
+      eq->next = prec_link_new (s2, transitive);
+    }
+  else
+    s1->equals = prec_link_new (s2, transitive);
+}
+
+
+/*---------------------------------------------------.
+| Add a precedence relationship S1 == S2, both ways. |
+`---------------------------------------------------*/
+
+static void
+add_prec_equal_link (prec_node *s1, prec_node *s2, bool transitive,
+                     location loc)
+{
+  if (is_prec_superior (s2, s1))
+    complain_contradicting_prec(&loc, s1->symbol->tag, s2->symbol->tag,
+                                '=', '>');
+  else if (is_prec_superior (s1, s2))
+    complain_contradicting_prec(&loc, s1->symbol->tag, s2->symbol->tag,
+                                '=', '<');
+  create_prec_equal_link (s1, s2, transitive, loc);
+  create_prec_equal_link (s2, s1, transitive, loc);
+}
+
+
+/*------------------------------------------------------------------------.
+| Add a symbol to the current declaration group, and declare the implicit |
+| precedence links. SAME_LINE is true if the symbol was declared in the   |
+| same statement as the previous one (same precedence level).             |
+`------------------------------------------------------------------------*/
+
+void
+add_to_current_group (sym_content *s, bool same_line)
+{
+  if (!same_line)
+    for (symbol_list *l = current_prec_declaration; l; l = l->next)
+      {
+        sym_content *symb = l->content.sym->content;
+        if (!current_group->symbol_list)
+          current_group->symbol_list = symb;
+        else
+          {
+            sym_content *sym = current_group->symbol_list;
+            while (sym->group_next)
+              sym = sym->group_next;
+            sym->group_next = symb;
+          }
+      }
+
+  if (current_group->symbol_list)
+    for (sym_content *sym = current_group->symbol_list; sym;
+         sym = sym->group_next)
+      add_prec_link (s->prec_node, sym->prec_node, true,
+                     s->prec_node->prec_location);
+
+  if (!same_line)
+    {
+      symbol_list_prec_free (current_prec_declaration);
+      current_prec_declaration = malloc (sizeof *current_prec_declaration);
+      current_prec_declaration->content.sym = s->symbol;
+      current_prec_declaration->next = NULL;
+    }
+  else
+    {
+      symbol_list *l = current_prec_declaration;
+      for (; true; l = l->next)
+        {
+          add_prec_equal_link (s->prec_node, 
l->content.sym->content->prec_node,
+                               true, s->prec_node->prec_location);
+          if (!l->next)
+            break;
+        }
+      l->next = malloc (sizeof *l->next);
+      l->next->content.sym = s->symbol;
+      l->next->next = NULL;
+    }
+}
+
+/*-----------------------------------------.
+| Create a new prec_node for the symbol s. |
+`-----------------------------------------*/
+
+static prec_node *
+prec_node_new (symbol * s)
+{
+  prec_node * res = malloc (sizeof *res);
+  res->symbol = s;
+  res->assoc = undef_assoc;
+  res->sons = NULL;
+  res-> equals = NULL;
+  return res;
+}
+
+
 /*--------------------------.
 | Create a new sym_content. |
 `--------------------------*/
@@ -78,12 +329,14 @@ sym_content_new (symbol *s)
 
   res->number = NUMBER_UNDEFINED;
   res->prec = 0;
-  res->assoc = undef_assoc;
   res->user_token_number = USER_NUMBER_UNDEFINED;
 
   res->class = unknown_sym;
   res->status = undeclared;
 
+  res->group_next = NULL;
+  res->prec_node = prec_node_new (s);
+
   return res;
 }
 
@@ -116,6 +369,28 @@ symbol_new (uniqstr tag, location loc)
   return res;
 }
 
+void
+prec_link_free (prec_link * l)
+{
+  if (l)
+    {
+      prec_link_free (l->next);
+      free (l);
+    }
+}
+
+/*--------------------.
+| Free one prec_node. |
+`--------------------*/
+
+static void
+prec_node_free (prec_node * n)
+{
+  prec_link_free (n->sons);
+  prec_link_free (n->equals);
+  free (n);
+}
+
 /*--------------------.
 | Free a sym_content. |
 `--------------------*/
@@ -123,6 +398,7 @@ symbol_new (uniqstr tag, location loc)
 static void
 sym_content_free (sym_content *sym)
 {
+  prec_node_free (sym->prec_node);
   free (sym);
 }
 
@@ -367,14 +643,16 @@ symbol_precedence_set (symbol *sym, int prec, assoc a, 
location loc)
   sym_content *s = sym->content;
   if (a != undef_assoc)
     {
-      if (s->prec)
+      if (s->prec_node->assoc != undef_assoc)
         symbol_redeclaration (sym, assoc_to_string (a),
-                              s->prec_location, loc);
+                              s->prec_node->prec_location, loc);
       else
         {
           s->prec = prec;
-          s->assoc = a;
-          s->prec_location = loc;
+          s->prec_node->assoc = a;
+          s->prec_node->prec_location = loc;
+          add_to_current_group (s, prec == current_prec_level);
+          current_prec_level = prec;
         }
     }
 
@@ -684,6 +962,38 @@ hash_semantic_type_hasher (void const *m, size_t tablesize)
   return hash_semantic_type (m, tablesize);
 }
 
+/*-------------------------------------.
+| Symbol precedence group hash table.  |
+`-------------------------------------*/
+
+static struct hash_table *group_table = NULL;
+
+static inline bool
+hash_compare_group (const symgroup *m1, const symgroup *m2)
+{
+  /* Since tags are unique, we can compare the pointers themselves.  */
+  return UNIQSTR_EQ (m1->tag, m2->tag);
+}
+
+static bool
+hash_group_comparator (void const *m1, void const *m2)
+{
+  return hash_compare_group (m1, m2);
+}
+
+static inline size_t
+hash_group (const symgroup *m, size_t tablesize)
+{
+  /* Since tags are unique, we can hash the pointer itself.  */
+  return ((uintptr_t) m->tag) % tablesize;
+}
+
+static size_t
+hash_group_hasher (void const *m, size_t tablesize)
+{
+  return hash_group (m, tablesize);
+}
+
 /*-------------------------------.
 | Create the symbol hash table.  |
 `-------------------------------*/
@@ -701,6 +1011,12 @@ symbols_new (void)
                                          hash_semantic_type_hasher,
                                          hash_semantic_type_comparator,
                                          free);
+  group_table = hash_initialize (HT_INITIAL_CAPACITY,
+                                  NULL,
+                                  hash_group_hasher,
+                                  hash_group_comparator,
+                                  free);
+  set_current_group (DEFAULT_GROUP_NAME, NULL);
 }
 
 
@@ -815,9 +1131,11 @@ symbols_free (void)
 {
   hash_free (symbol_table);
   hash_free (semantic_type_table);
+  hash_free (group_table);
   free (symbols);
   free (symbols_sorted);
   free (semantic_types_sorted);
+  symbol_list_prec_free (current_prec_declaration);
 }
 
 
@@ -1102,8 +1420,8 @@ static inline bool
 is_assoc_useless (symbol *s)
 {
   return s
-      && s->content->assoc != undef_assoc
-      && s->content->assoc != precedence_assoc
+      && s->content->prec_node->assoc != undef_assoc
+      && s->content->prec_node->assoc != precedence_assoc
       && !used_assoc[s->content->number];
 }
 
@@ -1136,21 +1454,110 @@ print_precedence_warnings (void)
     {
       symbol *s = symbols[i];
       if (s
-          && s->content->prec != 0
           && !prec_nodes[i]->pred
           && !prec_nodes[i]->succ)
         {
           if (is_assoc_useless (s))
-            complain (&s->content->prec_location, Wprecedence,
+            complain (&s->content->prec_node->prec_location, Wprecedence,
                       _("useless precedence and associativity for %s"), 
s->tag);
-          else if (s->content->assoc == precedence_assoc)
-            complain (&s->content->prec_location, Wprecedence,
+          else if (s->content->prec_node->assoc == precedence_assoc)
+            complain (&s->content->prec_node->prec_location, Wprecedence,
                       _("useless precedence for %s"), s->tag);
         }
       else if (is_assoc_useless (s))
-        complain (&s->content->prec_location, Wprecedence,
+        complain (&s->content->prec_node->prec_location, Wprecedence,
                   _("useless associativity for %s, use %%precedence"), s->tag);
     }
   free (used_assoc);
   assoc_free ();
 }
+
+/*------------------------------------------------.
+| Counter to create unique anonymous group names. |
+`------------------------------------------------*/
+
+static unsigned int anon_group_counter = 0;
+
+/*-------------------------------------------------.
+| Return a new unique name for an anonymous group. |
+`-------------------------------------------------*/
+
+uniqstr new_anonymous_group_name (void)
+{
+  char buff[20];
+  snprintf (buff, 20, "__anon%u__", anon_group_counter++);
+  return uniqstr_new (buff);
+}
+
+/*-------------------------------------------.
+| Constructor for a symbol precedence group. |
+`-------------------------------------------*/
+
+symgroup *
+symgroup_new (const uniqstr tag, location loc)
+{
+  symgroup *group = xmalloc (sizeof (*group));
+  group->tag = tag;
+  group->symbol_list = NULL;
+  group->location = loc;
+  return group;
+}
+
+/*--------------------------------------------------------------------------.
+| Get the symbol precedence group by that name. If not present, a new group |
+| is created and inserted in the table, with the location information       |
+| provided, if any.                                                         |
+`--------------------------------------------------------------------------*/
+
+symgroup *
+symgroup_from_uniqstr (const uniqstr key, location *loc)
+{
+  bool null_loc = loc == NULL;
+  if (null_loc)
+    {
+      loc = malloc (sizeof *loc);
+      boundary_set (&loc->start, uniqstr_new (""), 1, 1);
+      boundary_set (&loc->end, uniqstr_new (""), 1, 1);
+    }
+  symgroup probe;
+  symgroup *entry;
+
+  probe.tag = key;
+  entry = hash_lookup (group_table, &probe);
+
+  if (!entry)
+    {
+      /* First insertion in the hash. */
+      entry = symgroup_new (key, *loc);
+      if (!hash_insert (group_table, entry))
+        xalloc_die ();
+    }
+  if (null_loc)
+    free (loc);
+  return entry;
+}
+
+/*--------------------------------------------------------------------------.
+| Change the current group to the one designated by the name, and create it |
+| if necessary. The location information is used for creation if available. |
+`--------------------------------------------------------------------------*/
+
+void set_current_group (const uniqstr tag, location *loc)
+{
+  for (symbol_list *l = current_prec_declaration; l; l = l->next)
+    {
+      sym_content *symb = l->content.sym->content;
+      if (!current_group->symbol_list)
+        current_group->symbol_list = symb;
+      else
+        {
+          sym_content *sym = current_group->symbol_list;
+          for (; sym->group_next; sym = sym->group_next)
+            {}
+          sym->group_next = symb;
+        }
+    }
+  symbol_list_prec_free (current_prec_declaration);
+  current_prec_declaration = NULL;
+  current_group = symgroup_from_uniqstr (tag, loc);
+}
diff --git a/src/symtab.h b/src/symtab.h
index 18e6805..5c042b0 100644
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -129,9 +129,10 @@ struct sym_content
   code_props props[CODE_PROPS_SIZE];
 
   symbol_number number;
-  location prec_location;
+
+  /* Not used anymore, to remove. */
   int prec;
-  assoc assoc;
+
   int user_token_number;
 
   symbol_class class;
@@ -317,6 +318,18 @@ struct symgroup
     location location;
 } ;
 
+/** Get a dummy name for an anonymous group. */
+uniqstr new_anonymous_group_name (void);
+
+/** Set the current group in the token precedence declaration to a new group
+ * with this name */
+void set_current_group (const uniqstr name, location *loc);
+
+/** Get or create the group by that name. The location information is used for
+ *  creation when available. */
+symgroup *
+symgroup_from_uniqstr (const uniqstr key, location *loc);
+
 /*----------------------------------.
 | Graph of precedence relationships |
 `----------------------------------*/
@@ -348,6 +361,13 @@ enum prec_rel_comparator
     prec_superior,
     prec_superior_strict,
 };
+/** Check if s1 and s2 have the same precedence level. */
+bool is_prec_equal (prec_node * s1, prec_node * s2);
+
+/** Check if from > to . */
+bool is_prec_superior (prec_node * from, prec_node * to);
+
+
 /*-----------------.
 | Semantic types.  |
 `-----------------*/
diff --git a/tests/existing.at b/tests/existing.at
index a1b95ac..a883225 100644
--- a/tests/existing.at
+++ b/tests/existing.at
@@ -484,7 +484,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 
      NAME      [reduce using rule 152 (opt_variable)]
      '$'       [reduce using rule 152 (opt_variable)]
-@@ -5379,7 +5379,7 @@
+@@ -5385,7 +5385,7 @@
    156         | . '$' non_post_simp_exp
 
      NAME  shift, and go to state 9
@@ -493,7 +493,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 
      NAME      [reduce using rule 152 (opt_variable)]
      '$'       [reduce using rule 152 (opt_variable)]
-@@ -5399,7 +5399,7 @@
+@@ -5405,7 +5405,7 @@
    156         | . '$' non_post_simp_exp
 
      NAME  shift, and go to state 9
@@ -502,7 +502,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 
      NAME      [reduce using rule 152 (opt_variable)]
      '$'       [reduce using rule 152 (opt_variable)]
-@@ -6214,7 +6214,7 @@
+@@ -6220,7 +6220,7 @@
    156         | . '$' non_post_simp_exp
 
      NAME  shift, and go to state 9
@@ -511,7 +511,7 @@ dnl   - 61 -> 328: reduce -> shift on '*', '/', and '%'
 
      NAME      [reduce using rule 152 (opt_variable)]
      '$'       [reduce using rule 152 (opt_variable)]
-@@ -11099,3 +11099,274 @@
+@@ -11117,3 +11117,274 @@
     45 statement: LEX_FOR '(' opt_exp semi opt_nls exp semi opt_nls opt_exp 
r_paren opt_nls statement .
 
      $default  reduce using rule 45 (statement)
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]