+ // FIXME: this method needs to be cleaned up and documented
+ private void sortReductions() {
+ // crude algorithm to assing an ordinal ordering to every position
+ // al will be sorted in DECREASING order (al[0] >= al[1])
+ ArrayList<Sequence.Position> al = new ArrayList<Sequence.Position>();
+ for(State s : all_states) {
+ for(Object po : s) {
+ Sequence.Position p = (Sequence.Position)po;
+ if (al.contains(p)) continue;
+ int i=0;
+ for(; i<al.size(); i++) {
+ if (comparePositions(p, al.get(i)) < 0)
+ break;
+ }
+ al.add(i, p);
+ }
+ }
+ // FIXME: this actually pollutes the "pure" objects (the ones that should not be modified by the Parser)
+ // sort in increasing order...
+ OUTER: while(true) {
+ for(int i=0; i<al.size(); i++)
+ for(int j=i+1; j<al.size(); j++)
+ if (comparePositions(al.get(i), al.get(j)) > 0) {
+ Sequence.Position p = al.remove(j);
+ al.add(i, p);
+ continue OUTER;
+ }
+ break;
+ }
+
+ int j = 1;
+ int pk = 0;
+ for(int i=0; i<al.size(); i++) {
+ boolean inc = false;
+ for(int k=pk; k<i; k++) {
+ if (comparePositions(al.get(k), al.get(i)) > 0)
+ { inc = true; break; }
+ }
+ inc = true;
+ if (inc) {
+ j++;
+ pk = i;
+ }
+ al.get(i).ord = j;
+ }
+ }
+
+ /**
+ * A single state in the LR table and the transitions
+ * possible from it
+ *
+ * A state corresponds to a set of Sequence.Position's. Each
+ * Node in the GSS has a State; the Node represents a set of
+ * possible parses, one for each Position in the State.
+ *
+ * Every state is either "doomed" or "normal". If a Position
+ * is part of a Sequence which is a conjunct (that is, it was
+ * passed to Sequence.{and(),andnot()}), then that Position
+ * will appear only in doomed States. Furthermore, any set
+ * of Positions reachable from a doomed State also forms a
+ * doomed State. Note that in this latter case, a doomed
+ * state might have exactly the same set of Positions as a
+ * non-doomed state.
+ *
+ * Nodes with non-doomed states represent nodes which
+ * contribute to actual valid parses. Nodes with doomed
+ * States exist for no other purpose than to enable/disable
+ * some future reduction from a non-doomed Node. Because of
+ * this, we "garbage-collect" Nodes with doomed states if
+ * there are no more non-doomed Nodes which they could
+ * affect (see Result, Reduction, and Node for details).
+ *
+ * Without this optimization, many seemingly-innocuous uses
+ * of positive and negative conjuncts can trigger O(n^2)
+ * space+time complexity in otherwise simple grammars. There
+ * is an example of this in the regression suite.
+ */
+ class State<Token> implements IntegerMappable, Iterable<Position> {