001    // -*- mode: java -*-
002    /* Copyright 2000, 2001, Compaq Computer Corporation */
003    
004    /* IF THIS IS A JAVA FILE, DO NOT EDIT IT!  
005    
006       Most Java files in this directory which are part of the Javafe AST
007       are automatically generated using the astgen comment (see
008       ESCTools/Javafe/astgen) from the input file 'hierarchy.h'.  If you
009       wish to modify AST classes or introduce new ones, modify
010       'hierarchy.j.'
011     */
012    
013    package javafe.ast;
014    
015    import javafe.util.Assert;
016    import javafe.util.Location;
017    import javafe.util.ErrorSet;
018    
019    // Convention: unless otherwise noted, integer fields named "loc" refer
020    // to the location of the first character of the syntactic unit
021    
022    
023    /* ---------------------------------------------------------------------- */
024    
025    /**
026     * Treated as an immutable type. <p>
027     *
028     * Invariant: There is always at least one element in a Name.
029     */
030    
031    public abstract class Name extends ASTNode
032    {
033        /**
034         * Return our printname, which will be of one of the forms X, X.Y,
035         * X.Y.Z, ...
036         */
037        //@ pure
038        public abstract /*@non_null*/ String printName();
039    
040        /**
041         * Return a hash code for <code>this</code> such that two
042         * <code>Name</code>s that are <code>equals</code> have the same
043         * hash code.
044         */
045        public abstract int hashCode();
046    
047        /**
048         * Return true if <code>other</code> is a <code>Name</code> that
049         * is component-wise equal to <code>this</code>.
050         */
051        public abstract boolean equals(Object other);
052    
053        /**
054         * The number of identifiers we contain.
055         */
056        //@ invariant length >= 1;
057        /*@ ghost public int length; */
058    
059        /** Return the number of identifiers in <code>this</code>. */
060        //@ ensures \result==length;
061        //@ pure
062        public abstract int size();
063    
064        /**
065         * Return the ith identifier of <code>this</code>.
066         */
067        //@ requires 0 <= i && i<length;
068        //@ pure
069        public abstract /*@non_null*/ Identifier identifierAt(int i);
070    
071        /**
072         * Return the location of the ith identifier of <code>this</code>.
073         */
074        //@ requires 0 <= i && i<length;
075        //@ ensures \result != Location.NULL;
076        //@ pure
077        public abstract int locIdAt(int i);
078    
079        /**
080         * Return the location of the dot after the ith identifier of
081         * <code>this</code>.
082         */
083        //@ requires 0 <= i && i<length-1;
084        //@ ensures \result != Location.NULL;
085        //@ pure
086        public abstract int locDotAfter(int i);
087    
088        /**
089         * Return the first <code>len</code> identifiers in
090         * <code>this</code> in an array.  Requires that <code>len</code>
091         * be between 0 and length of <code>this</code> inclusive.
092         */
093        //@ requires 0 <= len && len <= length;
094        //@ ensures \nonnullelements(\result);
095        //@ ensures \result.length == len;
096        //@ pure
097        public abstract String[] toStrings(int len);
098    
099        /**
100         * Return all identifiers in <code>this</code> in an array.
101         */
102        //@ ensures \nonnullelements(\result);
103        //@ ensures \result.length == length;
104        //@ pure
105        public String[] toStrings() {
106            return toStrings(size());
107        }
108    
109        /**
110         * Make a <code>Name</code> with the given identifiers and
111         * locations.  Caller must forget about the Vecs/arrays passed
112         * here.
113         */
114        //@ requires ids.count>0;
115        //@ requires ids.count==locIds.length && ids.count==locDots.length+1;
116        /*@ requires (\forall int i; (0 <= i && i<locIds.length)
117                            ==> locIds[i] != Location.NULL); */
118        /*@ requires (\forall int i; (0 <= i && i<locDots.length)
119                            ==> locDots[i] != Location.NULL); */
120        //@ pure
121        public static /*@non_null*/ Name make(/*@non_null*/ int[] locIds, /*@non_null*/ int[] locDots, /*@non_null*/ IdentifierVec ids) {
122            int sz = ids.size();
123            Assert.precondition(sz > 0 && locIds.length == sz
124                            && locDots.length + 1 == sz);
125            if (sz == 1)
126                return SimpleName.make(ids.elementAt(0), locIds[0]);
127            else
128                return CompoundName.make(ids, locIds, locDots);
129        }
130    
131        /**
132         * Make a <code>Name</code> whose locations are all
133         * <code>loc</code> from a <code>String</code>.
134         *
135         * <p> This routine parses a non-empty <code>String</code> consisting
136         * of a series of dot-separated components into a <code>Name</code>.
137         * 
138         * precondition: <code>N.length()>0</code><p>
139         */
140        //@ requires N.length()>0;
141        //@ requires loc != Location.NULL;
142        //@ pure
143        public static /*@non_null*/ Name make(/*@non_null*/ String N, int loc) {
144            // Convert N to a list of its components:
145            String[] components = javafe.filespace.StringUtil.parseList(N, '.');
146            int sz = components.length;
147            Assert.notFalse(sz>0);          //@ nowarn Pre;
148    
149            // Convert the components to Identifiers:
150            IdentifierVec ids = IdentifierVec.make();
151            for(int i = 0; i < sz; i++)
152                ids.addElement(Identifier.intern(components[i]));
153    
154            if (sz == 1)
155                return SimpleName.make(ids.elementAt(0), loc);
156    
157            int[] newLocIds = new int[sz];
158            int[] newLocDots = new int[sz-1];
159            for(int i = 0; i < sz; i++)
160                newLocIds[i] = loc;
161            for(int i = 0; i < sz-1; i++)
162                newLocDots[i] = loc;
163    
164            return make(newLocIds, newLocDots, ids);
165        }
166    
167        /**
168         * Return a <code>Name</code> consisting of the first
169         * <code>len</code> identifiers of <code>this</code>.  Requires
170         * that <code>len</code> is greater than zero and less than or
171         * equal to the length of <code>this</code>.
172         */
173        //@ requires 0<len && len <= length;
174        //@ pure
175        public abstract /*@non_null*/ Name prefix(int len);
176    
177        /**
178         * Override getEndLoc so it refers to the actual end of us.
179         */
180        public /*@ pure @*/ int getEndLoc() {
181            return Location.inc(getStartLoc(),
182                                Math.max(0, printName().length()-1));
183        }
184    
185        /**
186         * Avoid allocating more than one of these.
187         */
188        //@ invariant \nonnullelements(emptyStringArray);
189        //@ invariant emptyStringArray.length == 0;
190        final protected static String[] emptyStringArray = new String[0];
191    
192    
193    
194    // Generated boilerplate constructors:
195    
196       protected Name() {
197          super();
198       }
199       public void check() {
200          super.check();
201       }
202    
203    }