All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.java_cup.internal.lalr_item_set Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */


package com.sun.java_cup.internal;

import java.util.Hashtable;
import java.util.Enumeration;

/** This class represents a set of LALR items.  For purposes of building
 *  these sets, items are considered unique only if they have unique cores
 *  (i.e., ignoring differences in their lookahead sets).

* * This class provides fairly conventional set oriented operations (union, * sub/super-set tests, etc.), as well as an LALR "closure" operation (see * compute_closure()). * * @see com.sun.java_cup.internal.lalr_item * @see com.sun.java_cup.internal.lalr_state * @version last updated: 3/6/96 * @author Scott Hudson */ public class lalr_item_set { /*-----------------------------------------------------------*/ /*--- Constructor(s) ----------------------------------------*/ /*-----------------------------------------------------------*/ /** Constructor for an empty set. */ public lalr_item_set() { } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Constructor for cloning from another set. * @param other indicates set we should copy from. */ public lalr_item_set(lalr_item_set other) throws internal_error { not_null(other); _all = (Hashtable)other._all.clone(); } /*-----------------------------------------------------------*/ /*--- (Access to) Instance Variables ------------------------*/ /*-----------------------------------------------------------*/ /** A hash table to implement the set. We store the items using themselves * as keys. */ protected Hashtable _all = new Hashtable(11); /** Access to all elements of the set. */ public Enumeration all() {return _all.elements();} /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Cached hashcode for this set. */ protected Integer hashcode_cache = null; /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Size of the set */ public int size() {return _all.size();} /*-----------------------------------------------------------*/ /*--- Set Operation Methods ---------------------------------*/ /*-----------------------------------------------------------*/ /** Does the set contain a particular item? * @param itm the item in question. */ public boolean contains(lalr_item itm) {return _all.containsKey(itm);} /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Return the item in the set matching a particular item (or null if not * found) * @param itm the item we are looking for. */ public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);} /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Is this set an (improper) subset of another? * @param other the other set in question. */ public boolean is_subset_of(lalr_item_set other) throws internal_error { not_null(other); /* walk down our set and make sure every element is in the other */ for (Enumeration e = all(); e.hasMoreElements(); ) if (!other.contains((lalr_item)e.nextElement())) return false; /* they were all there */ return true; } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Is this set an (improper) superset of another? * @param other the other set in question. */ public boolean is_superset_of(lalr_item_set other) throws internal_error { not_null(other); return other.is_subset_of(this); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Add a singleton item, merging lookahead sets if the item is already * part of the set. returns the element of the set that was added or * merged into. * @param itm the item being added. */ public lalr_item add(lalr_item itm) throws internal_error { lalr_item other; not_null(itm); /* see if an item with a matching core is already there */ other = (lalr_item)_all.get(itm); /* if so, merge this lookahead into the original and leave it */ if (other != null) { other.lookahead().add(itm.lookahead()); return other; } /* otherwise we just go in the set */ else { /* invalidate cached hashcode */ hashcode_cache = null; _all.put(itm,itm); return itm; } } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Remove a single item if it is in the set. * @param itm the item to remove. */ public void remove(lalr_item itm) throws internal_error { not_null(itm); /* invalidate cached hashcode */ hashcode_cache = null; /* remove it from hash table implementing set */ _all.remove(itm); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Add a complete set, merging lookaheads where items are already in * the set * @param other the set to be added. */ public void add(lalr_item_set other) throws internal_error { not_null(other); /* walk down the other set and do the adds individually */ for (Enumeration e = other.all(); e.hasMoreElements(); ) add((lalr_item)e.nextElement()); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Remove (set subtract) a complete set. * @param other the set to remove. */ public void remove(lalr_item_set other) throws internal_error { not_null(other); /* walk down the other set and do the removes individually */ for (Enumeration e = other.all(); e.hasMoreElements(); ) remove((lalr_item)e.nextElement()); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Remove and return one item from the set (done in hash order). */ public lalr_item get_one() throws internal_error { Enumeration the_set; lalr_item result; the_set = all(); if (the_set.hasMoreElements()) { result = (lalr_item)the_set.nextElement(); remove(result); return result; } else return null; } /*-----------------------------------------------------------*/ /*--- General Methods ---------------------------------------*/ /*-----------------------------------------------------------*/ /** Helper function for null test. Throws an interal_error exception if its * parameter is null. * @param obj the object we are testing. */ protected void not_null(Object obj) throws internal_error { if (obj == null) throw new internal_error("Null object used in set operation"); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Compute the closure of the set using the LALR closure rules. Basically * for every item of the form:

   *    [L ::= a *N alpha, l] 
   *  
* (where N is a a non terminal and alpha is a string of symbols) make * sure there are also items of the form:
   *    [N ::= *beta, first(alpha l)] 
   *  
* corresponding to each production of N. Items with identical cores but * differing lookahead sets are merged by creating a new item with the same * core and the union of the lookahead sets (the LA in LALR stands for * "lookahead merged" and this is where the merger is). This routine * assumes that nullability and first sets have been computed for all * productions before it is called. */ public void compute_closure() throws internal_error { lalr_item_set consider; lalr_item itm, new_itm, add_itm; non_terminal nt; terminal_set new_lookaheads; Enumeration p; production prod; boolean need_prop; /* invalidate cached hashcode */ hashcode_cache = null; /* each current element needs to be considered */ consider = new lalr_item_set(this); /* repeat this until there is nothing else to consider */ while (consider.size() > 0) { /* get one item to consider */ itm = consider.get_one(); /* do we have a dot before a non terminal */ nt = itm.dot_before_nt(); if (nt != null) { /* create the lookahead set based on first after dot */ new_lookaheads = itm.calc_lookahead(itm.lookahead()); /* are we going to need to propagate our lookahead to new item */ need_prop = itm.lookahead_visible(); /* create items for each production of that non term */ for (p = nt.productions(); p.hasMoreElements(); ) { prod = (production)p.nextElement(); /* create new item with dot at start and that lookahead */ new_itm = new lalr_item(prod, new terminal_set(new_lookaheads)); /* add/merge item into the set */ add_itm = add(new_itm); /* if propagation is needed link to that item */ if (need_prop) itm.add_propagate(add_itm); /* was this was a new item*/ if (add_itm == new_itm) { /* that may need further closure, consider it also */ consider.add(new_itm); } } } } } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality comparison. */ public boolean equals(lalr_item_set other) { if (other == null || other.size() != size()) return false; /* once we know they are the same size, then improper subset does test */ try { return is_subset_of(other); } catch (internal_error e) { /* can't throw error from here (because superclass doesn't) so crash */ e.crash(); return false; } } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Generic equality comparison. */ public boolean equals(Object other) { if (!(other instanceof lalr_item_set)) return false; else return equals((lalr_item_set)other); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Return hash code. */ public int hashCode() { int result = 0; Enumeration e; int cnt; /* only compute a new one if we don't have it cached */ if (hashcode_cache == null) { /* hash together codes from at most first 5 elements */ // CSA fix! we'd *like* to hash just a few elements, but // that means equal sets will have inequal hashcodes, which // we're not allowed (by contract) to do. So hash them all. for (e = all(), cnt=0 ; e.hasMoreElements() /*&& cnt<5*/; cnt++) result ^= ((lalr_item)e.nextElement()).hashCode(); hashcode_cache = new Integer(result); } return hashcode_cache.intValue(); } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Convert to string. */ public String toString() { StringBuffer result = new StringBuffer(); result.append("{\n"); for (Enumeration e=all(); e.hasMoreElements(); ) { result.append(" " + (lalr_item)e.nextElement() + "\n"); } result.append("}"); return result.toString(); } /*-----------------------------------------------------------*/ }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy