    001    /* Copyright 2000, 2001, Compaq Computer Corporation */
    002
    003    package javafe.parser;
    004
    005    import javafe.ast.*;
    006    import javafe.util.StackVector;
    007    import javafe.util.ErrorSet;
    008    import javafe.util.Location;
    009
    010    /**
    011     * Base class for Java parser; provides some basic parsing utilities.
    012     *
    013     * @see javafe.ast.ASTNode
    014     * @see javafe.parser.ParseType
    015     * @see javafe.parser.Parse
    016     */
    017
    018    public class ParseUtil
    019    {
    020        public ParseUtil() {
    021            //@ set seqModifierPragma.elementType = \type(ModifierPragma);
    022            //@ set seqModifierPragma.owner = this;
    023        }
    024
    025
    026        //----------------------- Misc Helper Functions ----------------------------
    027
    028        /** Raises a <TT>RuntimeException</TT> with the argument string. */
    029
    030        // @ ensures false;
    031        // UNUSED private static void fail(String m) { ErrorSet.fatal(m); }
    032
    033        /** Raises a <TT>RuntimeException</TT> with the argument string
    034            including a textual representation of the given source location. */
    035        //@ requires loc != Location.NULL;
    036        //@ ensures false;
    037        public static void fail(int loc, String m) { ErrorSet.fatal(loc, m); }
    038
    039        //@ requires loc != Location.NULL;
    040        public static void error(int loc, String m) { ErrorSet.error(loc, m); }
    041
    042        /**
    043         Takes an expected token from the input stream,
    044         calls <TT>fail</TT> on error.
    045         */
    046        //@ requires l != null && l.m_in != null;
    047        //@ modifies l.ttype, l.auxVal, l.identifierVal;
    048        //@ ensures \old(l.ttype)==expected;
    049        public void expect(Lex l, int expected) {
    050            if( l.ttype != expected )
    051                fail(l.startingLoc,
    052                     "Unexpected token '" + PrettyPrint.inst.toString(l.ttype) +
    053                     "', expected '" + PrettyPrint.inst.toString(expected)+"'");
    054            l.getNextToken();
    055        }
    056
    057        /**
    058
    059         Converts operator tokens to corresponding AST tag.
    060         Tokens INC and DEC get mapped to PREFIXINC and PREFIXDEC
    061
    062         */
    063
    064        int operatorTokenToTag(int token) {
    065            // Right now we have the identity mapping.
    066            return token;
    067        }
    068
    069
    070        /*------------------------ Modifiers -------------------------------*/
    071
    072        //* Internal working storage for parse*Modifier* functions
    073        //@ invariant seqModifierPragma.elementType == \type(ModifierPragma);
    074        //@ invariant seqModifierPragma.owner == this;
    075        protected final StackVector seqModifierPragma = new StackVector();
    076
    077        /**
    078         * Keyword at index i in this array corresponds to bit i in
    079         * modifier bitset.  Thus PRIVATE is at index 1, ACC_PRIVATE =
    080         * 1<<1.
    081         * These are in the same bit order as the values in
    082         * java.lang.reflect.Modifier, and should remain that way, though
    083         * I don't know if any code uses that fact (it might come in handy
    084         * in reading class files, for example).
    085         */
    086        public static final int modifierKeywords[] = {
    087            TagConstants.PUBLIC, TagConstants.PRIVATE, TagConstants.PROTECTED,
    088            TagConstants.STATIC, TagConstants.FINAL,
    089            TagConstants.SYNCHRONIZED, TagConstants.VOLATILE,
    090            TagConstants.TRANSIENT, TagConstants.NATIVE,
    091            -1, // Don't consider 'interface' to be a modifier
    092            TagConstants.ABSTRACT, TagConstants.STRICT
    093        };
    094
    095
    096        /**
    097         * Parse a list of modifier pragmas.  Returns <code>null</code> if
    098         * <code>l</code> does not point to a modifier pragma.  Otherwise,
    099         * reads <code>l</code> until there are no more modifier pragmas and
    100         * returns the resulting list.
    101         */
    102        //@ requires l.m_in != null;
    103        public ModifierPragmaVec parseModifierPragmas(/*@ non_null @*/ Lex l) {
    104            if (l.ttype != TagConstants.MODIFIERPRAGMA)
    105                return null;
    106
    107            seqModifierPragma.push();
    108            do {
    109                seqModifierPragma.addElement(l.auxVal);
    110                l.getNextToken();
    111            } while (l.ttype == TagConstants.MODIFIERPRAGMA);
    112            return ModifierPragmaVec.popFromStackVector(seqModifierPragma);
    113        }
    114
    115        /**
    116         * Parse a list of modifier pragmas and adds them to an existing
    117         * <code>ModifierPragmaVec</code>.  If the existing
    118         * <code>ModifierPragmaVec</code> was <code>null</code>, then it
    119         * either returns <code>null</code> (if <code>l</code> does not point
    120         * to a modifier pragma), or returns a new
    121         * <code>ModifierPragmaVec</code>.
    122         */
    123        //@ requires l.m_in != null;
    124        public ModifierPragmaVec parseMoreModifierPragmas(/*@ non_null @*/ Lex l,
    125                                                          ModifierPragmaVec orig)
    126        {
    127            ModifierPragmaVec modifierPragmas = parseModifierPragmas( l );
    128            if (modifierPragmas == null)
    129                return orig;
    130            else if (orig == null)
    131                return modifierPragmas;
    132            else {
    133                orig.append( modifierPragmas );
    134                return orig;
    135            }
    136        }
    137
    138        /** As a side effect, <code>parseModifiers</code> mutates this
    139         value. */
    140        public ModifierPragmaVec modifierPragmas;
    141
    142
    143        /**
    144         * Parse a list of modifiers.  Ensures no duplicate Java modifiers
    145         * and only one of the access modifiers public, protected,
    146         * private.  Return integer encoding the Java modifiers.
    147         *
    148         * <p> In addition to parsing Java modifiers, also handles modifier
    149         * pragmas (anything with a ttype of TagConstants.MODIFIERPRAGMA).
    150         * If no modifier pragmas are seen, sets
    151         * <c>modifierPragmas</c> to <c>null</c>.  Otherwise, sets it to
    152         * be the list of modifier pragmas seen in the course of parsing any
    153         * Java modifiers.
    154         *
    155         * @see javafe.ast.Modifiers
    156         */
    157        //@ requires l.m_in != null;
    158        //@ modifies modifierPragmas;
    159        public int parseModifiers(/*@ non_null @*/ Lex l) {
    160            boolean seenPragma = false;
    161            int modifiers = Modifiers.NONE;
    162
    163            getModifierLoop:
    164            for(;;) {
    165                if (l.ttype == TagConstants.MODIFIERPRAGMA) {
    166                    if (! seenPragma) {
    167                            seqModifierPragma.push();
    168                            seenPragma = true;
    169                    }
    170                    seqModifierPragma.addElement(l.auxVal);
    171                    l.getNextToken();
    172                    continue getModifierLoop;
    173                } else {
    174                    int i = getJavaModifier(l,modifiers);
    175                    if (i != 0) {
    176                        modifiers |= i;
    177                        continue getModifierLoop;
    178                    }
    179                }
    180                // Next token is not a modifier
    181                if (! seenPragma)
    182                    modifierPragmas = null;
    183                else
    184                    modifierPragmas
    185                        = ModifierPragmaVec.popFromStackVector(seqModifierPragma);
    186                return modifiers;
    187            }
    188        }
    189
    190        /** Checks if the next token is a Java modifier.  Returns 0
    191            if it is not; returns an int with the modifier bit turned on
    192            if it is.  Also issues an error if the modifier is already
    193            present in the modifiers argument (use 0 for this argument
    194            to turn off these errors).
    195            Note that the bit that is found is not ORed into the modifiers
    196            int; you have to do that outside this call.
    197            The Lex is advanced if a modifier is found.
    198        */
    199        public int getJavaModifier(Lex l, int modifiers) {
    200            for( int i=0; i<modifierKeywords.length; i++ ) {
    201                if( l.ttype == modifierKeywords[i] ) {
    202                    // Token is modifier keyword
    203                    int modifierBit = 1<<i;
    204                    if( (modifiers & modifierBit) != 0 ) {
    205                        ErrorSet.caution(l.startingLoc,
    206                            "Duplicate occurrence of modifier '"
    207                             +PrettyPrint.inst.toString(l.ttype)+"'");
    208                    } else if( (modifiers & Modifiers.ACCESS_MODIFIERS) != 0 &&
    209                        (modifierBit & Modifiers.ACCESS_MODIFIERS) != 0 ) {
    210                        ErrorSet.error(l.startingLoc,
    211                             "Cannot have more than one of the access modifiers "+
    212                             "public, protected, private");
    213                    }
    214                    l.getNextToken();
    215                    return modifierBit;
    216                }
    217            }
    218            return 0;
    219        }
    220
    221        public boolean isJavaModifier(int ttype) {
    222            for( int i=0; i<modifierKeywords.length; i++ ) {
    223                if( ttype == modifierKeywords[i] ) return true;
    224            }
    225            return false;
    226        }
    227
    228        static public String arrayToString(Object[] a, String sep) {
    229            if (a==null || a.length == 0) return "";
    230            else {
    231                    StringBuffer sb = new StringBuffer();
    232                    sb.append(a[0].toString());
    233                    for (int i=1; i<a.length; ++i) {
    234                        sb.append(sep);
    235                        sb.append(a[i].toString());
    236                    }
    237                    return sb.toString();
    238            }
    239        }
    240    }