2
* STANDARD ML OF NEW JERSEY COPYRIGHT NOTICE, LICENSE AND DISCLAIMER.
4
* Copyright (c) 1989-1998 by Lucent Technologies
6
* Permission to use, copy, modify, and distribute this software and its
7
* documentation for any purpose and without fee is hereby granted, provided
8
* that the above copyright notice appear in all copies and that both the
9
* copyright notice and this permission notice and warranty disclaimer appear
10
* in supporting documentation, and that the name of Lucent Technologies, Bell
11
* Labs or any Lucent entity not be used in advertising or publicity pertaining
12
* to distribution of the software without specific, written prior permission.
14
* Lucent disclaims all warranties with regard to this software, including all
15
* implied warranties of merchantability and fitness. In no event shall Lucent
16
* be liable for any special, indirect or consequential damages or any damages
17
* whatsoever resulting from loss of use, data or profits, whether in an action
18
* of contract, negligence or other tortious action, arising out of or in
19
* connection with the use or performance of this software.
21
* Taken from this URL:
22
* http://www.smlnj.org/license.html
24
* This license is compatible with the GNU GPL (see section "Standard ML of New
25
* Jersey Copyright License"):
26
* http://www.gnu.org/licenses/license-list.html#StandardMLofNJ
30
* Copyright 1996-1999 by Scott Hudson, Frank Flannery, C. Scott Ananian
33
package weka.core.parser.java_cup;
35
import java.util.Hashtable;
36
import java.util.Enumeration;
38
/** This class represents a set of LALR items. For purposes of building
39
* these sets, items are considered unique only if they have unique cores
40
* (i.e., ignoring differences in their lookahead sets).<p>
42
* This class provides fairly conventional set oriented operations (union,
43
* sub/super-set tests, etc.), as well as an LALR "closure" operation (see
46
* @see weka.core.parser.java_cup.lalr_item
47
* @see weka.core.parser.java_cup.lalr_state
48
* @version last updated: 3/6/96
49
* @author Scott Hudson
52
public class lalr_item_set {
54
/*-----------------------------------------------------------*/
55
/*--- Constructor(s) ----------------------------------------*/
56
/*-----------------------------------------------------------*/
58
/** Constructor for an empty set. */
59
public lalr_item_set() { }
61
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
63
/** Constructor for cloning from another set.
64
* @param other indicates set we should copy from.
66
public lalr_item_set(lalr_item_set other)
70
_all = (Hashtable)other._all.clone();
73
/*-----------------------------------------------------------*/
74
/*--- (Access to) Instance Variables ------------------------*/
75
/*-----------------------------------------------------------*/
77
/** A hash table to implement the set. We store the items using themselves
80
protected Hashtable _all = new Hashtable(11);
82
/** Access to all elements of the set. */
83
public Enumeration all() {return _all.elements();}
85
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
87
/** Cached hashcode for this set. */
88
protected Integer hashcode_cache = null;
90
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
92
/** Size of the set */
93
public int size() {return _all.size();}
95
/*-----------------------------------------------------------*/
96
/*--- Set Operation Methods ---------------------------------*/
97
/*-----------------------------------------------------------*/
99
/** Does the set contain a particular item?
100
* @param itm the item in question.
102
public boolean contains(lalr_item itm) {return _all.containsKey(itm);}
104
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
106
/** Return the item in the set matching a particular item (or null if not
108
* @param itm the item we are looking for.
110
public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);}
112
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
114
/** Is this set an (improper) subset of another?
115
* @param other the other set in question.
117
public boolean is_subset_of(lalr_item_set other) throws internal_error
121
/* walk down our set and make sure every element is in the other */
122
for (Enumeration e = all(); e.hasMoreElements(); )
123
if (!other.contains((lalr_item)e.nextElement()))
126
/* they were all there */
130
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
132
/** Is this set an (improper) superset of another?
133
* @param other the other set in question.
135
public boolean is_superset_of(lalr_item_set other) throws internal_error
138
return other.is_subset_of(this);
141
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
143
/** Add a singleton item, merging lookahead sets if the item is already
144
* part of the set. returns the element of the set that was added or
146
* @param itm the item being added.
148
public lalr_item add(lalr_item itm) throws internal_error
154
/* see if an item with a matching core is already there */
155
other = (lalr_item)_all.get(itm);
157
/* if so, merge this lookahead into the original and leave it */
160
other.lookahead().add(itm.lookahead());
163
/* otherwise we just go in the set */
166
/* invalidate cached hashcode */
167
hashcode_cache = null;
174
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
176
/** Remove a single item if it is in the set.
177
* @param itm the item to remove.
179
public void remove(lalr_item itm) throws internal_error
183
/* invalidate cached hashcode */
184
hashcode_cache = null;
186
/* remove it from hash table implementing set */
190
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
192
/** Add a complete set, merging lookaheads where items are already in
194
* @param other the set to be added.
196
public void add(lalr_item_set other) throws internal_error
200
/* walk down the other set and do the adds individually */
201
for (Enumeration e = other.all(); e.hasMoreElements(); )
202
add((lalr_item)e.nextElement());
205
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
207
/** Remove (set subtract) a complete set.
208
* @param other the set to remove.
210
public void remove(lalr_item_set other) throws internal_error
214
/* walk down the other set and do the removes individually */
215
for (Enumeration e = other.all(); e.hasMoreElements(); )
216
remove((lalr_item)e.nextElement());
219
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
221
/** Remove and return one item from the set (done in hash order). */
222
public lalr_item get_one() throws internal_error
228
if (the_set.hasMoreElements())
230
result = (lalr_item)the_set.nextElement();
238
/*-----------------------------------------------------------*/
239
/*--- General Methods ---------------------------------------*/
240
/*-----------------------------------------------------------*/
242
/** Helper function for null test. Throws an interal_error exception if its
244
* @param obj the object we are testing.
246
protected void not_null(Object obj) throws internal_error
249
throw new internal_error("Null object used in set operation");
252
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
254
/** Compute the closure of the set using the LALR closure rules. Basically
255
* for every item of the form: <pre>
256
* [L ::= a *N alpha, l]
258
* (where N is a a non terminal and alpha is a string of symbols) make
259
* sure there are also items of the form: <pre>
260
* [N ::= *beta, first(alpha l)]
262
* corresponding to each production of N. Items with identical cores but
263
* differing lookahead sets are merged by creating a new item with the same
264
* core and the union of the lookahead sets (the LA in LALR stands for
265
* "lookahead merged" and this is where the merger is). This routine
266
* assumes that nullability and first sets have been computed for all
267
* productions before it is called.
269
public void compute_closure()
270
throws internal_error
272
lalr_item_set consider;
273
lalr_item itm, new_itm, add_itm;
275
terminal_set new_lookaheads;
282
/* invalidate cached hashcode */
283
hashcode_cache = null;
285
/* each current element needs to be considered */
286
consider = new lalr_item_set(this);
288
/* repeat this until there is nothing else to consider */
289
while (consider.size() > 0)
291
/* get one item to consider */
292
itm = consider.get_one();
294
/* do we have a dot before a non terminal */
295
nt = itm.dot_before_nt();
298
/* create the lookahead set based on first after dot */
299
new_lookaheads = itm.calc_lookahead(itm.lookahead());
301
/* are we going to need to propagate our lookahead to new item */
302
need_prop = itm.lookahead_visible();
304
/* create items for each production of that non term */
305
for (p = nt.productions(); p.hasMoreElements(); )
307
prod = (production)p.nextElement();
309
/* create new item with dot at start and that lookahead */
310
new_itm = new lalr_item(prod,
311
new terminal_set(new_lookaheads));
313
/* add/merge item into the set */
314
add_itm = add(new_itm);
315
/* if propagation is needed link to that item */
317
itm.add_propagate(add_itm);
319
/* was this was a new item*/
320
if (add_itm == new_itm)
322
/* that may need further closure, consider it also */
323
consider.add(new_itm);
330
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
332
/** Equality comparison. */
333
public boolean equals(lalr_item_set other)
335
if (other == null || other.size() != size()) return false;
337
/* once we know they are the same size, then improper subset does test */
339
return is_subset_of(other);
340
} catch (internal_error e) {
341
/* can't throw error from here (because superclass doesn't) so crash */
348
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
350
/** Generic equality comparison. */
351
public boolean equals(Object other)
353
if (!(other instanceof lalr_item_set))
356
return equals((lalr_item_set)other);
359
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
361
/** Return hash code. */
362
public int hashCode()
368
/* only compute a new one if we don't have it cached */
369
if (hashcode_cache == null)
371
/* hash together codes from at most first 5 elements */
372
// CSA fix! we'd *like* to hash just a few elements, but
373
// that means equal sets will have inequal hashcodes, which
374
// we're not allowed (by contract) to do. So hash them all.
375
for (e = all(), cnt=0 ; e.hasMoreElements() /*&& cnt<5*/; cnt++)
376
result ^= ((lalr_item)e.nextElement()).hashCode();
378
hashcode_cache = new Integer(result);
381
return hashcode_cache.intValue();
384
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
386
/** Convert to string. */
387
public String toString()
389
StringBuffer result = new StringBuffer();
391
result.append("{\n");
392
for (Enumeration e=all(); e.hasMoreElements(); )
394
result.append(" " + (lalr_item)e.nextElement() + "\n");
398
return result.toString();
400
/*-----------------------------------------------------------*/