1 /* Lookahead sensitive state item searches for counterexample generation
3 Copyright (C) 2020-2021 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>. */
24 #include <gl_linked_list.h>
31 // Lookahead sensitive state item.
36 // this is the precise lookahead set (follow_L from the CupEx paper)
42 new_lssi (state_item_number si
, lssi
*p
, bitset l
, bool free_l
)
44 lssi
*res
= xmalloc (sizeof *res
);
48 res
->free_lookahead
= free_l
;
57 if (sn
->free_lookahead
)
58 bitset_free (sn
->lookahead
);
63 lssi_hasher (lssi
*sn
, size_t max
)
66 bitset_iterator biter
;
68 BITSET_FOR_EACH (biter
, sn
->lookahead
, syn
, 0)
74 lssi_comparator (lssi
*s1
, lssi
*s2
)
78 if (s1
->lookahead
== s2
->lookahead
)
80 return bitset_equal_p (s1
->lookahead
, s2
->lookahead
);
85 typedef gl_list_t lssi_list
;
88 append_lssi (lssi
*sn
, Hash_table
*visited
, lssi_list queue
)
90 if (hash_lookup (visited
, sn
))
92 sn
->free_lookahead
= false;
96 hash_xinsert (visited
, sn
);
97 gl_list_add_last (queue
, sn
);
106 print_state_item (&state_items
[l
->si
], out
);
109 fprintf (out
, "FOLLOWL = { ");
110 bitset_iterator biter
;
112 BITSET_FOR_EACH (biter
, l
->lookahead
, sin
, 0)
113 fprintf (out
, "%s, \n", symbols
[sin
]->tag
);
114 fprintf (out
, "}\n");
120 * Compute the set of state-items that can reach the given conflict item via
121 * a combination of transitions or production steps.
124 eligible_state_items (state_item
*target
)
126 bitset result
= bitset_create (nstate_items
, BITSET_FIXED
);
127 state_item_list queue
=
128 gl_list_create (GL_LINKED_LIST
, NULL
, NULL
, NULL
, true, 1,
129 (const void **) &target
);
130 while (gl_list_size (queue
) > 0)
132 state_item
*si
= (state_item
*) gl_list_get_at (queue
, 0);
133 gl_list_remove_at (queue
, 0);
134 if (bitset_test (result
, si
- state_items
))
136 bitset_set (result
, si
- state_items
);
137 // search all reverse edges.
138 bitset rsi
= si
->revs
;
139 bitset_iterator biter
;
140 state_item_number sin
;
141 BITSET_FOR_EACH (biter
, rsi
, sin
, 0)
142 gl_list_add_last (queue
, &state_items
[sin
]);
144 gl_list_free (queue
);
149 * Compute the shortest lookahead-sensitive path from the start state to
150 * this conflict. If optimized is true, only consider parser states
151 * that can reach the conflict state.
154 shortest_path_from_start (state_item_number target
, symbol_number next_sym
)
156 bitset eligible
= eligible_state_items (&state_items
[target
]);
157 Hash_table
*visited
= hash_initialize (32,
159 (Hash_hasher
) lssi_hasher
,
160 (Hash_comparator
) lssi_comparator
,
161 (Hash_data_freer
) lssi_free
);
162 bitset il
= bitset_create (nsyms
, BITSET_FIXED
);
164 lssi
*init
= new_lssi (0, NULL
, il
, true);
165 lssi_list queue
= gl_list_create_empty (GL_LINKED_LIST
, NULL
, NULL
,
167 append_lssi (init
, visited
, queue
);
168 // breadth-first search
169 bool finished
= false;
171 while (gl_list_size (queue
) > 0)
173 n
= (lssi
*) gl_list_get_at (queue
, 0);
174 gl_list_remove_at (queue
, 0);
175 state_item_number last
= n
->si
;
176 if (target
== last
&& bitset_test (n
->lookahead
, next_sym
))
181 state_item
*si
= &state_items
[last
];
182 // Transitions don't change follow_L
185 if (bitset_test (eligible
, si
->trans
))
187 lssi
*next
= new_lssi (si
->trans
, n
, n
->lookahead
, false);
188 append_lssi (next
, visited
, queue
);
191 // For production steps, follow_L is based on the symbol after the
192 // nonterminal being produced.
193 // if no such symbol exists, follow_L is unchanged
194 // if the symbol is a terminal, follow_L only contains that terminal
195 // if the symbol is not nullable, follow_L is its FIRSTS set
196 // if the symbol is nullable, follow_L is its FIRSTS set unioned with
197 // this logic applied to the next symbol in the rule
200 // Compute follow_L as above
201 bitset lookahead
= bitset_create (nsyms
, BITSET_FIXED
);
202 item_number
*pos
= si
->item
+ 1;
203 for (; !item_number_is_rule_number (*pos
); ++pos
)
205 item_number it
= *pos
;
208 bitset_set (lookahead
, it
);
213 bitset_union (lookahead
, lookahead
, FIRSTS (it
));
214 if (!nullable
[it
- ntokens
])
218 if (item_number_is_rule_number (*pos
))
219 bitset_union (lookahead
, n
->lookahead
, lookahead
);
221 bool lookahead_used
= false;
222 // Try all possible production steps within this parser state.
223 bitset_iterator biter
;
224 state_item_number nextSI
;
225 BITSET_FOR_EACH (biter
, si
->prods
, nextSI
, 0)
227 if (!bitset_test (eligible
, nextSI
))
229 lssi
*next
= new_lssi (nextSI
, n
, lookahead
,
231 lookahead_used
= append_lssi (next
, visited
, queue
)
235 bitset_free (lookahead
);
239 bitset_free (eligible
);
242 gl_list_free (queue
);
243 fputs ("Cannot find shortest path to conflict state.", stderr
);
246 state_item_list res
=
247 gl_list_create_empty (GL_LINKED_LIST
, NULL
, NULL
, NULL
, true);
248 for (lssi
*sn
= n
; sn
!= NULL
; sn
= sn
->parent
)
249 gl_list_add_first (res
, &state_items
[sn
->si
]);
252 gl_list_free (queue
);
254 if (trace_flag
& trace_cex
)
256 fputs ("REDUCE ITEM PATH:\n", stderr
);
257 gl_list_iterator_t it
= gl_list_iterator (res
);
259 while (gl_list_iterator_next (&it
, &sip
, NULL
))
260 state_item_print ((state_item
*) sip
, stderr
, "");
266 * Determine if the given terminal is in the given symbol set or can begin
267 * a nonterminal in the given symbol set.
270 intersect_symbol (symbol_number sym
, bitset syms
)
274 bitset_iterator biter
;
276 BITSET_FOR_EACH (biter
, syms
, sn
, 0)
280 if (ISVAR (sn
) && bitset_test (FIRSTS (sn
), sym
))
287 * Determine if any symbol in ts is in syms
288 * or can begin a nonterminal syms.
291 intersect (bitset ts
, bitset syms
)
295 bitset_iterator biter
;
297 BITSET_FOR_EACH (biter
, syms
, sn
, 0)
299 if (bitset_test (ts
, sn
))
301 if (ISVAR (sn
) && !bitset_disjoint_p (ts
, FIRSTS (sn
)))
309 * Compute a list of state_items that have a production to n with respect
313 lssi_reverse_production (const state_item
*si
, bitset lookahead
)
315 state_item_list result
=
316 gl_list_create_empty (GL_LINKED_LIST
, NULL
, NULL
, NULL
, true);
317 if (SI_TRANSITION (si
))
319 // A production step was made to the current lalr_item.
320 // Check that the next symbol in the parent lalr_item is
321 // compatible with the lookahead.
322 bitset_iterator biter
;
323 state_item_number sin
;
324 BITSET_FOR_EACH (biter
, si
->revs
, sin
, 0)
326 state_item
*prevsi
= &state_items
[sin
];
327 if (!production_allowed (prevsi
, si
))
329 bitset prev_lookahead
= prevsi
->lookahead
;
330 if (item_number_is_rule_number (*(prevsi
->item
)))
333 // Check that some lookaheads can be preserved.
334 if (!intersect (prev_lookahead
, lookahead
))
342 // Check that lookahead is compatible with the first
343 // possible symbols in the rest of the production.
344 // Alternatively, if the rest of the production is
345 // nullable, the lookahead must be compatible with
346 // the lookahead of the corresponding item.
347 bool applicable
= false;
349 for (item_number
*pos
= prevsi
->item
+ 1;
350 !applicable
&& nlable
&& item_number_is_symbol_number (*pos
);
353 symbol_number next_sym
= item_number_as_symbol_number (*pos
);
354 if (ISTOKEN (next_sym
))
356 applicable
= intersect_symbol (next_sym
, lookahead
);
361 applicable
= intersect (FIRSTS (next_sym
), lookahead
);
363 nlable
= nullable
[next_sym
- ntokens
];
366 if (!applicable
&& !nlable
)
370 gl_list_add_last (result
, prevsi
);