1 module ddparser.lr;
2 
3 import ddparser.gram;
4 import ddparser.util;
5 
6 import std.algorithm;
7 
8 enum INITIAL_ALLITEMS =	3359;
9 
10 private uint item_hash(Item* _i)
11 {
12     return  ((cast(uint)_i.rule.index << 8) + 			
13      (cast(uint)(_i.kind != ElemKind.ELEM_END ? _i.index : _i.rule.elems.length)));
14 }
15 
16 private int
17 insert_item(State *s, Elem *e) {
18   if (e !in s.items_hash) {
19     s.items_hash[e] = true;
20     s.items ~= e;
21     return 1;
22   }
23   return 0;
24 }
25 
26 bool itemIsLessThanItem(Item* a, Item* b)
27 {
28   return item_hash(a) < item_hash(b);
29 }
30 
31 private void
32 free_state(State *s) {
33   FREE(s);
34 }
35 
36 private State *
37 maybe_add_state(Grammar *g, State *s) {
38     foreach (i; g.states) {
39         if (s.hash == i.hash && s.items.length == i.items.length) {
40             bool cont = false;
41             for (int j = 0; j < s.items.length; j++)
42                 if (s.items[j] != i.items[j])
43                 {
44                     cont = true;
45                     break;
46                 }
47             if (!cont)
48             {
49                 free_state(s);
50                 return i;
51             }
52         }
53     }
54     s.index = cast(uint)g.states.length;
55     g.states ~= s;
56     return s;
57 }
58 
59 private Elem *
60 next_elem(Item *i) {
61   if (i.index + 1 >= i.rule.elems.length)
62     return i.rule.end;
63   else
64     return i.rule.elems[i.index + 1];
65 }
66 
67 private State *
68 build_closure(Grammar *g, State *s) {
69   for (int i = 0; i < s.items.length; i++) { // s.items may change during iteration
70     if (s.items[i].kind == ElemKind.ELEM_NTERM) {
71       foreach (r; s.items[i].e.nterm.rules)
72 	insert_item(s, r.elems.length ? 
73 		    r.elems[0] : r.end);
74     }
75   }
76   s.items.sort!itemIsLessThanItem();
77   s.hash = 0;
78   foreach (i; s.items)
79     s.hash += item_hash(i);
80   return maybe_add_state(g, s);
81 }
82 
83 private Elem *
84 clone_elem(Elem *e) {
85   Elem *ee = new Elem();
86   *ee = *e;
87   return ee;
88 }
89 
90 private void
91 add_goto(State *s, State *ss, Elem *e) {
92   Goto *g = new Goto();
93   g.state = ss;
94   g.elem = clone_elem(e);
95   s.gotos ~= g;
96 }
97 
98 private void
99 build_state_for(Grammar *g, State *s, Elem *e) {
100   State *ss = null;
101 
102   foreach (i; s.items) {
103     if (i.kind != ElemKind.ELEM_END && elemTermOrNtermEqual(*i, *e))
104     {
105       if (!ss) ss = new State();
106       insert_item(ss, next_elem(i));
107     }
108   }
109   if (ss)
110     add_goto(s, build_closure(g, ss), e);
111 }
112 
113 private void
114 build_new_states(Grammar *g) {
115   Elem e;
116   for (int i = 0; i < g.states.length; i++) { // g.states may change during iteration
117     foreach (t; g.terminals) {
118       e.term = t;
119       build_state_for(g, g.states[i], &e);
120     }
121     foreach (p; g.productions) {
122       e.nterm = p;
123       build_state_for(g, g.states[i], &e);
124     }
125   }
126 }
127 
128 private void
129 build_states_for_each_production(Grammar *g) {
130   foreach (p; g.productions)
131     if (!p.internal && p.elem) {
132       State *s = new State();
133       insert_item(s, p.elem);
134       p.state = build_closure(g, s);
135     }
136 }
137 
138 uint
139 elem_symbol(Grammar *g, Elem *e) {
140   if (e.kind == ElemKind.ELEM_NTERM)
141     return e.nterm.index;
142   else
143     return cast(uint)(g.productions.length + e.term.index);
144 }
145 
146 bool gotoIsLessThanGoto(Goto* a, Goto* b)
147 {
148     return a.state.index < b.state.index;
149 }
150 
151 private void
152 sort_Gotos(Grammar *g) {
153   foreach (s; g.states) {
154     s.gotos.sort!gotoIsLessThanGoto();
155   }
156 }
157 
158 private void
159 build_LR_sets(Grammar *g) {
160   State *s = new State();
161   insert_item(s, g.productions[0].rules[0].elems[0]);
162   build_closure(g, s);
163   build_states_for_each_production(g);
164   build_new_states(g);
165   sort_Gotos(g);
166 }
167 
168 private Action *
169 new_Action(Grammar *g, ActionKind akind, Term *aterm, Rule *arule, State *astate) {
170   Action *a = new Action();
171   a.kind = akind;
172   a.term = aterm;
173   a.rule = arule;
174   a.state = astate;
175   a.index = g.action_count++;
176   g.actions ~= a;
177   return a;
178 }
179 
180 void
181 free_Action(Action *a) {
182   FREE(a);
183 }
184 
185 private void
186 add_action(Grammar *g, State *s, ActionKind akind, Term *aterm, 
187 	   Rule *arule, State *astate) 
188 {
189   Action *a;
190   
191   if (akind == ActionKind.ACTION_REDUCE) {
192     /* eliminate duplicates */
193     foreach (i; s.reduce_actions)
194       if (i.rule == arule)
195 	return;
196     a = new_Action(g, akind, aterm, arule, astate);
197     s.reduce_actions ~= a;
198   } else {
199     /* eliminate duplicates */
200     foreach (i; s.shift_actions)
201       if (i.term == aterm &&
202 	  i.state == astate &&
203 	  i.kind == akind)
204 	return;
205     a = new_Action(g, akind, aterm, arule, astate);
206     s.shift_actions ~= a;
207   }
208 }
209 
210 private void 
211 init_LR(Grammar *g) {
212   g.action_count = 0;
213 }
214 
215 extern(C) private int 
216 actioncmp(const void *aa, const void *bb) {
217   Action *a = *cast(Action **)aa, b = *cast(Action **)bb;
218   int i, j;
219   if (a.kind == ActionKind.ACTION_SHIFT_TRAILING)
220     i = a.term.index + 11000000;
221   else if (a.kind == ActionKind.ACTION_SHIFT)
222     i = a.term.index + 1000000;
223   else
224     i = a.rule.index;
225   if (b.kind == ActionKind.ACTION_SHIFT_TRAILING)
226     j = b.term.index + 11000000;
227   else if (b.kind == ActionKind.ACTION_SHIFT)
228     j = b.term.index + 1000000;
229   else
230     j = b.rule.index;
231   return ((i > j) ? 1 : ((i < j) ? -1 : 0));
232 }
233 
234 bool actionIsLessThanAction(Action* a, Action* b)
235 {
236   int i, j;
237   if (a.kind == ActionKind.ACTION_SHIFT_TRAILING)
238     i = a.term.index + 11000000;
239   else if (a.kind == ActionKind.ACTION_SHIFT)
240     i = a.term.index + 1000000;
241   else
242     i = a.rule.index;
243   if (b.kind == ActionKind.ACTION_SHIFT_TRAILING)
244     j = b.term.index + 11000000;
245   else if (b.kind == ActionKind.ACTION_SHIFT)
246     j = b.term.index + 1000000;
247   else
248     j = b.rule.index;
249   return i < j;
250 }
251 
252 void
253 sort_VecAction(ref VecAction v) {
254   v.array.sort!actionIsLessThanAction();
255 }
256 
257 private void
258 build_actions(Grammar *g) {
259     foreach(s; g.states)
260     {
261         foreach(e; s.items)
262         {
263             if (e.kind != ElemKind.ELEM_END) {
264                 if (e.kind == ElemKind.ELEM_TERM) {
265                     foreach (z; s.gotos) {
266                         if (z.elem.kind == ElemKind.ELEM_TERM && z.elem.e.term == e.term)
267                             add_action(g, s, ActionKind.ACTION_SHIFT, 
268                                     e.term, null, z.state);
269                     }
270                 }
271             } else if (e.rule.prod.index)
272                 add_action(g, s, ActionKind.ACTION_REDUCE, null, e.rule, null);
273             else
274                 s.accept = 1;
275         }
276         sort_VecAction(s.shift_actions);
277         sort_VecAction(s.reduce_actions);
278     }
279 }
280 
281 State *
282 goto_State(State *s, Elem *e) {
283   foreach (i; s.gotos)
284     if (elemTermOrNtermEqual(*i.elem, *e))
285       return i.state;
286   return null;
287 }
288 
289 private Hint *
290 new_Hint(size_t d, State *s, Rule *r) {
291   Hint *h = new Hint();
292   h.depth = cast(uint)d;
293   h.state = s;
294   h.rule = r;
295   return h;
296 }
297 
298 bool isHintLessThanHint(Hint* a, Hint* b)
299 {
300   return (a.depth < b.depth) || (a.depth == b.depth && a.rule.index < b.rule.index);
301 }
302 
303 private void
304 build_right_epsilon_hints(Grammar *g) {
305   foreach (s; g.states) {
306       foreach (e; s.items) {
307           if (e.kind != ElemKind.ELEM_END) {
308               Rule *r = e.rule;
309               bool next = false;
310               for (int z = e.index; z < r.elems.length; z++) {
311                   if ((r.elems[z].kind != ElemKind.ELEM_NTERM ||
312                               !r.elems[z].nterm.nullable))
313                   {
314                       next = true;
315                       break;
316                   }
317               }
318               if (!next)
319               {
320                   State *ss = s;
321                   for (int z = e.index; z < r.elems.length; z++)
322                       ss = goto_State(ss, r.elems[z]);
323                   if (ss && r.elems.length)
324                       vec_add(&s.right_epsilon_hints, 
325                               new_Hint(r.elems.length - e.index - 1, ss, r));
326                   else { /* ignore for states_for_each_productions */ }
327               }
328           }
329       }
330       if (s.right_epsilon_hints.length > 1)
331           s.right_epsilon_hints.array.sort!isHintLessThanHint();
332   }
333 }
334 
335 private void
336 build_error_recovery(Grammar *g) {
337     foreach (s; g.states) {
338         foreach (i; s.items) {
339             Rule *r = i.rule;
340             if (r.elems.length > 1 &&
341                     r.elems[r.elems.length - 1].kind == ElemKind.ELEM_TERM &&
342                     r.elems[r.elems.length - 1].term.kind == TermKind.TERM_STRING)
343             {
344                 int depth = i.index;
345                 Elem *e = r.elems[r.elems.length - 1];
346                 bool done = false;
347                 foreach (erh; s.error_recovery_hints) {
348                     Rule *rr = erh.rule;
349                     Elem *ee = rr.elems[rr.elems.length - 1];
350                     if (e.term.string_ == ee.term.string_) 
351                     {
352                         if (erh.depth > depth)
353                             erh.depth = depth;
354                         done = true;
355                         break;
356                     }
357                 }
358                 if (!done)
359                 {
360                    vec_add(&s.error_recovery_hints, new_Hint(depth, null, r));
361                 }
362             }
363         }
364         s.error_recovery_hints.array.sort!isHintLessThanHint();
365     }
366 }
367 
368 void
369 build_LR_tables(Grammar *g) {
370   init_LR(g);
371   build_LR_sets(g);
372   build_actions(g);
373   build_right_epsilon_hints(g);
374   build_error_recovery(g);
375 }
376