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    }