    001    /* Copyright 2000, 2001, Compaq Computer Corporation */
    002
    003    package javafe.parser;
    004
    005    import javafe.util.Assert;
    006
    007    /**
    008     * <code>TagConstants</tt> is a class defining the constants used to
    009     * identify different kinds of tokens.
    010     */
    011
    012    public class TagConstants extends javafe.ast.TagConstants
    013    {
    014        public static final int EOF = javafe.ast.TagConstants.LAST_TAG + 1;
    015
    016        // Value tokens
    017        public static final int MAX_INT_PLUS_ONE = EOF + 1;
    018        public static final int MAX_LONG_PLUS_ONE = MAX_INT_PLUS_ONE + 1;
    019
    020        // Pragma tokens
    021        public static final int LEXICALPRAGMA = MAX_LONG_PLUS_ONE + 1;
    022        public static final int MODIFIERPRAGMA = LEXICALPRAGMA + 1;
    023        public static final int POSTMODIFIERPRAGMA = MODIFIERPRAGMA + 1;
    024        public static final int STMTPRAGMA = POSTMODIFIERPRAGMA + 1;
    025        public static final int TYPEDECLELEMPRAGMA = STMTPRAGMA + 1;
    026        public static final int TYPEMODIFIERPRAGMA = TYPEDECLELEMPRAGMA + 1;
    027
    028        public static final int UNKNOWN_KEYWORD = TYPEMODIFIERPRAGMA + 1;
    029
    030        // Some punctuation tokens (rest come from OperatorTags)
    031        public static final int COMMA = UNKNOWN_KEYWORD + 1;
    032        public static final int SEMICOLON = COMMA + 1;
    033        public static final int LBRACE = SEMICOLON + 1;
    034        public static final int RBRACE = LBRACE + 1;
    035        public static final int LPAREN = RBRACE + 1;
    036        public static final int RPAREN = LPAREN + 1;
    037        public static final int LSQBRACKET = RPAREN + 1;
    038        public static final int RSQBRACKET = LSQBRACKET + 1;
    039
    040        public static final int QUESTIONMARK = RSQBRACKET + 1;
    041        public static final int COLON = QUESTIONMARK + 1;
    042
    043        public static final int FIELD = COLON + 1;
    044
    045        public static final int C_COMMENT = FIELD + 1;
    046        public static final int EOL_COMMENT = C_COMMENT + 1;
    047
    048        // Keywords
    049        public static final int FIRST_KEYWORD = EOL_COMMENT + 1;
    050        public static final int ABSTRACT = FIRST_KEYWORD;
    051        public static final int ASSERT   = ABSTRACT + 1;
    052        public static final int BOOLEAN  = ASSERT + 1;
    053        public static final int BREAK    = BOOLEAN + 1;
    054        public static final int BYTE     = BREAK + 1;
    055        public static final int CASE     = BYTE + 1;
    056        public static final int CATCH    = CASE + 1;
    057        public static final int CHAR     = CATCH + 1;
    058        public static final int CLASS    = CHAR + 1;
    059        public static final int CONST    = CLASS + 1;
    060        public static final int CONTINUE = CONST + 1;
    061        public static final int DEFAULT  = CONTINUE + 1;
    062        public static final int DO       = DEFAULT + 1;
    063        public static final int DOUBLE   = DO + 1;
    064        public static final int ELSE     = DOUBLE + 1;
    065        public static final int EXTENDS  = ELSE + 1;
    066        public static final int FALSE    = EXTENDS + 1;
    067        public static final int FINAL    = FALSE + 1;
    068        public static final int FINALLY  = FINAL + 1;
    069        public static final int FLOAT    = FINALLY + 1;
    070        public static final int FOR      = FLOAT + 1;
    071        public static final int GOTO     = FOR + 1;
    072        public static final int IF       = GOTO + 1;
    073        public static final int IMPLEMENTS = IF + 1;
    074        public static final int IMPORT   = IMPLEMENTS + 1;
    075        public static final int INSTANCEOF = IMPORT + 1;
    076        public static final int INT      = INSTANCEOF + 1;
    077        public static final int INTERFACE= INT + 1;
    078        public static final int LONG     = INTERFACE + 1;
    079        public static final int NATIVE   = LONG + 1;
    080        public static final int NEW      = NATIVE + 1;
    081        public static final int NULL     = NEW + 1;
    082        public static final int PACKAGE  = NULL + 1;
    083        public static final int PRIVATE  = PACKAGE + 1;
    084        public static final int PROTECTED= PRIVATE + 1;
    085        public static final int PUBLIC   = PROTECTED + 1;
    086        public static final int RETURN   = PUBLIC + 1;
    087        public static final int SHORT    = RETURN + 1;
    088        public static final int STATIC   = SHORT + 1;
    089        public static final int STRICT   = STATIC + 1;
    090        public static final int SUPER    = STRICT + 1;
    091        public static final int SWITCH   = SUPER + 1;
    092        public static final int SYNCHRONIZED = SWITCH + 1;
    093        public static final int THIS     = SYNCHRONIZED + 1;
    094        public static final int THROW    = THIS + 1;
    095        public static final int THROWS   = THROW + 1;
    096        public static final int TRANSIENT= THROWS + 1;
    097        public static final int TRUE     = TRANSIENT + 1;
    098        public static final int TRY      = TRUE + 1;
    099        public static final int VOID     = TRY + 1;
    100        public static final int VOLATILE = VOID + 1;
    101        public static final int WHILE    = VOLATILE + 1;
    102        public static final int LAST_KEYWORD = WHILE;
    103
    104        public static final int LAST_TAG = LAST_KEYWORD;
    105
    106        /**
    107         * @return text representation of <code>code</code> (e.g., "=" for
    108         * <tt>ASSIGN</tt>).  Requires <code>code</code> is one of the
    109         * token constants defined in <code>Tokens</code> (including ones
    110         * inherited from <code>OperatorTags</code>).
    111         */
    112
    113        //@ ensures \result != null;
    114        public static String toString(int code) {
    115            if (FIRST_KEYWORD <= code && code <= LAST_KEYWORD)
    116                return getString(code - FIRST_KEYWORD);
    117            for(int i = 1 + LAST_KEYWORD - FIRST_KEYWORD; i < noTokens; i++)
    118                if (getCode(i) == code) return getString(i);
    119
    120            if (code <= javafe.ast.TagConstants.LAST_TAG)
    121                return javafe.ast.TagConstants.toString(code);
    122
    123            return "Tag unknown to javafe.parser.TagConstants <" + code
    124                + " (+" + (code - javafe.ast.TagConstants.LAST_TAG) + ") >";
    125        }
    126
    127        /**
    128         * Alphabetical list of Java punctuation strings.  In addition to
    129         * being used in <code>Tokens</code>, this variable is used by
    130         * <code>Lex</code> to implement <code>addJavaPunctuation</code>.
    131         */
    132
    133        //@ invariant \nonnullelements(punctuationStrings);
    134        static final /*@ non_null @*/ String punctuationStrings[] = {
    135            "!", "!=", "%", "%=", "&", "&&", "&=", "(", ")", "*", "*=",
    136            "+", "++", "+=", ",", "-", "--", "-=", ".", "/", "/=", ":", ";",
    137            "<", "<<", "<<=", "<=", "=", "==", ">", ">=", ">>", ">>=", ">>>", ">>>=",
    138            "?", "[", "]", "^", "^=", "{", "|", "|=", "||", "}", "~", "/*", "//"
    139        };
    140
    141        /**
    142         * List of codes for Java punctuation.  Order of this list agrees
    143         * with with order of punctuationStrings.  In addition to being
    144         * used in <code>Tokens</code>, this variable is used by
    145         * <code>Lex</code> to implement
    146         * <code>addJavaPunctuation</code>.
    147         */
    148
    149        //@ invariant punctuationCodes.length == punctuationStrings.length;
    150        /*@ invariant (\forall int i; 0 <= i && i <= punctuationCodes.length
    151         @           ==>  punctuationCodes[i] != TagConstants.IDENT &&
    152         @                punctuationCodes[i] != TagConstants.BOOLEANLIT &&
    153         @                punctuationCodes[i] != TagConstants.INTLIT &&
    154         @                punctuationCodes[i] != TagConstants.LONGLIT &&
    155         @                punctuationCodes[i] != TagConstants.FLOATLIT &&
    156         @                punctuationCodes[i] != TagConstants.DOUBLELIT &&
    157         @                punctuationCodes[i] != TagConstants.STRINGLIT &&
    158         @                punctuationCodes[i] != TagConstants.CHARLIT &&
    159         @                punctuationCodes[i] != TagConstants.LEXICALPRAGMA &&
    160         @                punctuationCodes[i] != TagConstants.MODIFIERPRAGMA &&
    161         @                punctuationCodes[i] != TagConstants.STMTPRAGMA &&
    162         @                punctuationCodes[i] != TagConstants.TYPEDECLELEMPRAGMA &&
    163         @                punctuationCodes[i] != TagConstants.TYPEMODIFIERPRAGMA); */
    164        //@ invariant punctuationCodes.owner instanceof TagConstants;
    165        //@ spec_public
    166        static final int punctuationCodes[] = {
    167            NOT, NE, MOD, ASGREM, BITAND, AND, ASGBITAND, LPAREN, RPAREN, STAR, ASGMUL,
    168            ADD, INC, ASGADD, COMMA, SUB, DEC, ASGSUB, FIELD, DIV, ASGDIV, COLON,
    169            SEMICOLON,
    170            LT, LSHIFT, ASGLSHIFT, LE, ASSIGN, EQ, GT, GE, RSHIFT, ASGRSHIFT, URSHIFT,
    171            ASGURSHIFT,
    172            QUESTIONMARK, LSQBRACKET, RSQBRACKET, BITXOR, ASGBITXOR, LBRACE, BITOR,
    173            ASGBITOR, OR, RBRACE, BITNOT, C_COMMENT, EOL_COMMENT
    174        };
    175
    176        /**
    177         * Alphabetical list of Java keywords.  The keyword codes are also
    178         * alphabetical, which means that if X is code of keyword K, then
    179         * keywordStrings[X - FIRST_KEYWORD] should equal K.
    180         */
    181
    182        //@ invariant keywordStrings.length == 1 + LAST_KEYWORD - FIRST_KEYWORD;
    183        //@ invariant \nonnullelements(keywordStrings);
    184        //@ spec_public
    185        private static final String keywordStrings[] = {
    186            "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char",
    187            "class", "const", "continue", "default", "do", "double", "else",
    188            "extends", "false", "final", "finally", "float", "for", "goto", "if",
    189            "implements", "import", "instanceof", "int", "interface", "long",
    190            "native", "new", "null",
    191            "package", "private", "protected", "public", "return",
    192            "short", "static", "strictfp", "super", "switch", "synchronized", "this",
    193            "throw", "throws", "transient", "true", "try", "void", "volatile", "while"
    194        };
    195
    196        //@ invariant \nonnullelements(otherStrings);
    197        //@ spec_public
    198        private static final String otherStrings[] = {
    199            "IDENT",
    200            "CHARLIT", "INTLIT", "2147483648",
    201            "LONGLIT", "9223372036854775808L", "FLOATLIT", "DOUBLELIT", "STRINGLIT",
    202            "LEXICALPRAGMA", "MODIFIERPRAGMA", "POSTMODIFIERPRAGMA",
    203            "STMTPRAGMA", "TYPEDECLELEMPRAGMA",
    204            "TYPEMODIFIERPRAGMA", "EOF"
    205        };
    206
    207        //@ invariant otherCodes.length == otherStrings.length;
    208        //@ spec_public
    209        private static final int otherCodes[] = {
    210            IDENT,
    211            CHARLIT, INTLIT, MAX_INT_PLUS_ONE,
    212            LONGLIT, MAX_LONG_PLUS_ONE, FLOATLIT, DOUBLELIT, STRINGLIT,
    213            LEXICALPRAGMA, MODIFIERPRAGMA, POSTMODIFIERPRAGMA,
    214            STMTPRAGMA, TYPEDECLELEMPRAGMA,
    215            TYPEMODIFIERPRAGMA, EOF
    216        };
    217
    218        //@ invariant noTokens == keywordStrings.length + punctuationStrings.length + otherStrings.length;
    219        //@ spec_public
    220        private static final int noTokens =
    221            keywordStrings.length + punctuationStrings.length + otherStrings.length;
    222
    223        //@ requires 0 <= index && index < noTokens;
    224        private static int getCode(int index) {
    225            Assert.precondition(0 <= index && index < noTokens);
    226            if (index < 1 + LAST_KEYWORD - FIRST_KEYWORD) return FIRST_KEYWORD + index;
    227            index -= 1 + LAST_KEYWORD - FIRST_KEYWORD;
    228            if (index < punctuationCodes.length) return punctuationCodes[index];
    229            index -= punctuationCodes.length;
    230            if (index < otherCodes.length) return otherCodes[index];
    231            index -= otherCodes.length;
    232            Assert.notFalse(false, "Bad invariant");
    233            return -1; // Dummy
    234        }
    235
    236        //@ requires 0 <= index && index < noTokens;
    237        //@ ensures \result != null;
    238        private static String getString(int index) {
    239            Assert.precondition(0 <= index && index < noTokens);
    240            if (index < keywordStrings.length)
    241                return keywordStrings[index];
    242            index -= keywordStrings.length;
    243            if (index < punctuationStrings.length)
    244                return punctuationStrings[index];
    245            index -= punctuationStrings.length;
    246            if (index < otherStrings.length)
    247                return otherStrings[index];
    248            index -= otherStrings.length;
    249            Assert.notFalse(false, "Bad invariant");
    250            return null; // Dummy
    251        }
    252
    253        /** Perform module-level checks. */
    254        public static void zzzz() {
    255            Assert.notFalse(noTokens == (keywordStrings.length
    256                                         + punctuationStrings.length
    257                                         + otherStrings.length));
    258            Assert.notFalse(noTokens == (keywordStrings.length
    259                                         + punctuationCodes.length
    260                                         + otherCodes.length));
    261            // Check for duplicates
    262            for(int i = 0; i < noTokens; i++)
    263                for(int j = i+1; j < noTokens; j++)
    264                    if (getCode(i) == getCode(j))
    265                        System.out.println("Duplicate (" + getCode(i) + ") at " +
    266                                           getString(i) + " " + getString(j));
    267        }
    268    }