FileDocCategorySizeDatePackage
GTKScanner.javaAPI DocJava SE 5 API25777Fri Aug 26 14:54:46 BST 2005com.sun.java.swing.plaf.gtk

GTKScanner

public class GTKScanner extends Object
author
Shannon Hickey
version
1.40 12/19/03

Fields Summary
public static final String
CHARS_a_2_z
public static final String
CHARS_A_2_Z
public static final String
CHARS_DIGITS
public static final int
TOKEN_EOF
public static final int
TOKEN_LEFT_PAREN
public static final int
TOKEN_RIGHT_PAREN
public static final int
TOKEN_LEFT_CURLY
public static final int
TOKEN_RIGHT_CURLY
public static final int
TOKEN_LEFT_BRACE
public static final int
TOKEN_RIGHT_BRACE
public static final int
TOKEN_EQUAL_SIGN
public static final int
TOKEN_COMMA
public static final int
TOKEN_NONE
public static final int
TOKEN_ERROR
public static final int
TOKEN_CHAR
public static final int
TOKEN_BINARY
public static final int
TOKEN_OCTAL
public static final int
TOKEN_INT
public static final int
TOKEN_HEX
public static final int
TOKEN_FLOAT
public static final int
TOKEN_STRING
public static final int
TOKEN_SYMBOL
public static final int
TOKEN_IDENTIFIER
public static final int
TOKEN_IDENTIFIER_NULL
public static final int
TOKEN_LAST
public static final int
ERR_UNKNOWN
public static final int
ERR_UNEXP_EOF
public static final int
ERR_UNEXP_EOF_IN_STRING
public static final int
ERR_UNEXP_EOF_IN_COMMENT
public static final int
ERR_NON_DIGIT_IN_CONST
public static final int
ERR_DIGIT_RADIX
public static final int
ERR_FLOAT_RADIX
public static final int
ERR_FLOAT_MALFORMED
String
whiteSpaceChars
String
identifierFirst
String
identifierNth
String
commentSingle
boolean
caseSensitive
boolean
scanCommentMulti
boolean
scanIdentifier
boolean
scanIdentifier1Char
boolean
scanIdentifierNULL
boolean
scanSymbols
boolean
scanBinary
boolean
scanOctal
boolean
scanFloat
boolean
scanHex
boolean
scanHexDollar
boolean
scanStringSq
boolean
scanStringDq
boolean
numbers2Int
boolean
int2Float
boolean
identifier2String
boolean
char2Token
boolean
symbol2Token
private String
inputName
private HashMap
symbolTable
private Reader
reader
int
currToken
TokenValue
currValue
int
currLine
int
currPosition
int
nextToken
TokenValue
nextValue
int
nextLine
int
nextPosition
int
currScope
private static int
nextUniqueScope
private static final int
CHAR_EOF
private static final int
CHAR_NONE
private int
peekedChar
private ScannerKey
lookupKey
private StringBuffer
sb
private TokenValue
value
private int
token
private int
ch
Constructors Summary
public GTKScanner()


      
        clearScanner();
    
Methods Summary
public voidaddSymbol(java.lang.String symbol, int value)

        if (symbol == null) {
            return;
        }

        ScannerKey key = lookupSymbol(symbol);

        if (key == null) {
            key = new ScannerKey(currScope, caseSensitive ? symbol : symbol.toLowerCase());
            symbolTable.put(key, key);
        }

        key.value = value;
    
private static intchar2int(int c, int base)

        if (c >= '0" && c <= '9") {
            c -= '0";
        } else if (c >= 'A" && c <= 'Z") {
            c -= 'A" - 10;
        } else if (c >= 'a" && c <= 'z") {
            c -= 'a" - 10;
        } else {
            return -1;
        }

        return c < base ? c : -1;
    
private voidcheckForIdentifier()

        if (ch != CHAR_EOF && identifierNth.indexOf(peekNextChar()) != -1) {
            token = TOKEN_IDENTIFIER;

            sb = new StringBuffer();
            sb.append((char)ch);

            do {
                ch = getChar();
                sb.append((char)ch);
                ch = peekNextChar();
            } while (ch != CHAR_EOF && identifierNth.indexOf(ch) != -1);

            ch = CHAR_EOF;
        } else if (scanIdentifier1Char) {
            token = TOKEN_IDENTIFIER;
            value.stringVal = String.valueOf((char)ch);

            ch = CHAR_EOF;
        }
    
public voidclearScanner()

        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ioe) {
            }
            
            reader = null;
        }

        inputName = null;
        
        currToken = TOKEN_NONE;
        currValue.clear();
        currLine = 1;
        currPosition = 0;

        nextToken = TOKEN_NONE;
        nextValue.clear();
        nextLine = 1;
        nextPosition = 0;

        currScope = 0;

        peekedChar = CHAR_NONE;
    
public voidclearSymbolTable()

        symbolTable.clear();
    
public booleancontainsSymbol(java.lang.String symbol)

        return lookupSymbol(symbol) != null;
    
private intgetChar()

        int ch = peekNextChar();

        if (ch != CHAR_EOF) {
            peekedChar = CHAR_NONE;

            if (ch == '\n") {
                nextPosition = 0;
                nextLine++;
            } else {
                nextPosition++;
            }
        }

        return ch;
    
public intgetToken()

        currToken = peekNextToken();
        currValue.copyFrom(nextValue);
        currLine = nextLine;
        currPosition = nextPosition;

        if (currToken != TOKEN_EOF) {
            nextToken = TOKEN_NONE;
        }

        return currToken;
    
public static intgetUniqueScopeID()

        return nextUniqueScope++;
    
private voidhandleOrdinaryChar()

        if (ch != CHAR_EOF) {
            if (char2Token) {
                token = ch;
            } else {
                token = TOKEN_CHAR;
                value.charVal = (char)ch;
            }

            ch = CHAR_EOF;
        }
    
private com.sun.java.swing.plaf.gtk.GTKScanner$ScannerKeylookupSymbol(java.lang.String symbol)

        lookupKey.scope = currScope;
        lookupKey.symbol = (caseSensitive ? symbol : symbol.toLowerCase());
        return (ScannerKey)symbolTable.get(lookupKey);
    
private intpeekNextChar()

        if (peekedChar == CHAR_NONE) {
            peekedChar = reader.read();
        }

        return peekedChar;
    
public intpeekNextToken()

        if (nextToken == TOKEN_NONE) {
            readAToken();

            switch(nextToken) {
                case TOKEN_SYMBOL:
                    if (symbol2Token) {
                        nextToken = (int)nextValue.longVal;
                    }
                    break;
                case TOKEN_IDENTIFIER:
                    if (identifier2String) {
                        nextToken = TOKEN_STRING;
                    }
                    break;
                case TOKEN_HEX:
                case TOKEN_OCTAL:
                case TOKEN_BINARY:
                    if (numbers2Int) {
                        nextToken = TOKEN_INT;
                    }
                    break;
            }

            if (nextToken == TOKEN_INT && int2Float) {
                nextToken = TOKEN_FLOAT;
                nextValue.doubleVal = nextValue.longVal;
            }            
        }

        return nextToken;
    
public voidprintMessage(java.lang.String message, boolean isError)

        System.err.print(inputName + ":" + currLine + ": ");

        if (isError) {
            System.err.print("error: ");
        }

        System.err.println(message);
    
private voidreadAToken()

        boolean inString = false;

        nextValue.clear();
        sb = null;

        do {
            value.clear();
            token = TOKEN_NONE;

            ch = getChar();
            
            if (!skipSpaceAndComments()) {
                token = TOKEN_ERROR;
                value.longVal = ERR_UNEXP_EOF_IN_COMMENT;
            } else if (scanIdentifier && ch != CHAR_EOF && identifierFirst.indexOf(ch) != -1) {
                checkForIdentifier();
                handleOrdinaryChar();
            } else {
                switch(ch) {
                    case CHAR_EOF:
                        token = TOKEN_EOF;
                        break;
                    case '"":
                        if (!scanStringDq) {
                            handleOrdinaryChar();
                        } else {
                            token = TOKEN_STRING;
                            inString = true;
                            
                            sb = new StringBuffer();

                            while ((ch = getChar()) != CHAR_EOF) {
                                if (ch == '"") {
                                    inString = false;
                                    break;
                                } else {
                                    if (ch == '\\") {
                                        ch = getChar();
                                        switch(ch) {
                                            case CHAR_EOF:
                                                break;
                                            case '\\":
                                                sb.append('\\");
                                                break;
                                            case 'n":
                                                sb.append('\n");
                                                break;
                                            case 'r":
                                                sb.append('\r");
                                                break;
                                            case 't":
                                                sb.append('\t");
                                                break;
                                            case 'f":
                                                sb.append('\f");
                                                break;
                                            case 'b":
                                                sb.append('\b");
                                                break;
                                            case '0":
                                            case '1":
                                            case '2":
                                            case '3":
                                            case '4":
                                            case '5":
                                            case '6":
                                            case '7":
                                                int i = ch - '0";
                                                int nextCh = peekNextChar();

                                                if (nextCh >= '0" && nextCh <= '7") {
                                                    ch = getChar();
                                                    i = i * 8 + ch - '0";
                                                    nextCh = peekNextChar();
                                                    if (nextCh >= '0" && nextCh <= '7") {
                                                        ch = getChar();
                                                        i = i * 8 + ch - '0";
                                                    }
                                                }

                                                sb.append((char)i);
                                                break;
                                            default:
                                                sb.append((char)ch);
                                                break;
                                        }
                                    } else {
                                        sb.append((char)ch);
                                    }
                                }
                            }

                            ch = CHAR_EOF;
                        }

                        break;
                    case '\'":
                        if (!scanStringSq) {
                            handleOrdinaryChar();
                        } else {
                            token = TOKEN_STRING;
                            inString = true;
                            
                            sb = new StringBuffer();

                            while ((ch = getChar()) != CHAR_EOF) {
                                if (ch == '\'") {
                                    inString = false;
                                    break;
                                } else {
                                    sb.append((char)ch);
                                }
                            }

                            ch = CHAR_EOF;
                        }

                        break;
                    case '$":
                        if (!scanHexDollar) {
                            handleOrdinaryChar();
                        } else {
                            token = TOKEN_HEX;
                            ch = getChar();
                            scanNumber(false);
                        }

                        break;
                    case '.":
                        if (!scanFloat) {
                            handleOrdinaryChar();
                        } else {
                            token = TOKEN_FLOAT;
                            ch = getChar();
                            scanNumber(true);
                        }

                        break;
                    case '0":
                        if (scanOctal) {
                            token = TOKEN_OCTAL;
                        } else {
                            token = TOKEN_INT;
                        }

                        ch = peekNextChar();

                        if (scanHex && (ch == 'x" || ch == 'X")) {
                            token = TOKEN_HEX;
                            getChar();
                            ch = getChar();
                            if (ch == CHAR_EOF) {
                                token = TOKEN_ERROR;
                                value.longVal = ERR_UNEXP_EOF;
                                break;
                            }

                            if (char2int(ch, 16) < 0) {
                                token = TOKEN_ERROR;
                                value.longVal = ERR_DIGIT_RADIX;
                                ch = CHAR_EOF;
                                break;
                            }
                        } else if (scanBinary && (ch == 'b" || ch == 'B")) {
                            token = TOKEN_BINARY;
                            getChar();
                            ch = getChar();
                            if (ch == CHAR_EOF) {
                                token = TOKEN_ERROR;
                                value.longVal = ERR_UNEXP_EOF;
                                break;
                            }

                            if (char2int(ch, 2) < 0) {
                                token = TOKEN_ERROR;
                                value.longVal = ERR_NON_DIGIT_IN_CONST;
                                ch = CHAR_EOF;
                                break;
                            }
                        } else {
                            ch = '0";
                        }

                        // purposely fall through
                    case '1":
                    case '2":
                    case '3":
                    case '4":
                    case '5":
                    case '6":
                    case '7":
                    case '8":
                    case '9":
                        scanNumber(false);
                        break;
                    default:
                        handleOrdinaryChar();
                        break;
                }
            }
        } while (ch != CHAR_EOF);

        if (inString) {
            token = TOKEN_ERROR;
            value.longVal = ERR_UNEXP_EOF_IN_STRING;
            sb = null;
        }

        if (sb != null) {
            value.stringVal = sb.toString();
            sb = null;
        }

        if (token == TOKEN_IDENTIFIER) {
            if (scanSymbols) {
                int scope = currScope;
                ScannerKey key = lookupSymbol(value.stringVal);

                if (key != null) {
                    value.stringVal = null;
                    token = TOKEN_SYMBOL;
                    value.longVal = key.value;
                }
            }

            if (token == TOKEN_IDENTIFIER && scanIdentifierNULL & value.stringVal.length() == 4) {
                if ("NULL".equals(caseSensitive ? value.stringVal : value.stringVal.toUpperCase())) {
                    token = TOKEN_IDENTIFIER_NULL;
                }
            }
        }

        nextToken = token;
        nextValue.copyFrom(value);
    
private voidscanNumber(boolean seenDot)

        boolean inNumber = true;

        if (token == TOKEN_NONE) {
            token = TOKEN_INT;
        }
        
        sb = new StringBuffer(seenDot ? "0." : "");
        sb.append((char)ch);

        do {
            boolean isExponent = (token == TOKEN_FLOAT && (ch == 'e" || ch == 'E"));

            ch = peekNextChar();

            if (char2int(ch, 36) >= 0
                    || (scanFloat && ch == '.")
                    || (isExponent && (ch == '+" || ch == '-"))) {
                ch = getChar();

                switch(ch) {
                    case '0":
                    case '1":
                    case '2":
                    case '3":
                    case '4":
                    case '5":
                    case '6":
                    case '7":
                    case '8":
                    case '9":
                        sb.append((char)ch);
                        break;
                    case '.":
                        if (token != TOKEN_INT && token != TOKEN_OCTAL) {
                            value.longVal = (token == TOKEN_FLOAT ? ERR_FLOAT_MALFORMED : ERR_FLOAT_RADIX);
                            token = TOKEN_ERROR;
                            inNumber = false;
                        } else {
                            token = TOKEN_FLOAT;
                            sb.append((char)ch);
                        }
                        break;
                    case '+":
                    case '-":
                        if (token != TOKEN_FLOAT) {
                            token = TOKEN_ERROR;
                            value.longVal = ERR_NON_DIGIT_IN_CONST;
                            inNumber = false;
                        } else {
                            sb.append((char)ch);
                        }
                        break;
                    case 'E":
                    case 'e":
                        if ((token != TOKEN_HEX && !scanFloat)
                                || (token != TOKEN_HEX
                                    && token != TOKEN_OCTAL
                                    && token != TOKEN_FLOAT
                                    && token != TOKEN_INT)) {
                            token = TOKEN_ERROR;
                            value.longVal = ERR_NON_DIGIT_IN_CONST;
                            inNumber = false;
                        } else {
                            if (token != TOKEN_HEX) {
                                token = TOKEN_FLOAT;
                            }
                            sb.append((char)ch);
                        }
                        break;
                    default:
                        if (token != TOKEN_HEX) {
                            token = TOKEN_ERROR;
                            value.longVal = ERR_NON_DIGIT_IN_CONST;
                        } else {
                            sb.append((char)ch);
                        }
                        break;
                }
            } else {
                inNumber = false;
            }
        } while (inNumber);

        try {
            switch(token) {
                case TOKEN_INT:
                    value.longVal = Long.parseLong(sb.toString(), 10);
                    break;
                case TOKEN_FLOAT:
                    value.doubleVal = Double.parseDouble(sb.toString());
                    break;
                case TOKEN_HEX:
                    value.longVal = Long.parseLong(sb.toString(), 16);
                    break;
                case TOKEN_OCTAL:
                    value.longVal = Long.parseLong(sb.toString(), 8);
                    break;
                case TOKEN_BINARY:
                    value.longVal = Long.parseLong(sb.toString(), 2);
                    break;
            }
        } catch (NumberFormatException nfe) {
            // PENDING(shannonh) - in some cases this could actually be ERR_DIGIT_RADIX
            token = TOKEN_ERROR;
            value.longVal = ERR_NON_DIGIT_IN_CONST;
        }

        sb = null;
        ch = CHAR_EOF;
    
public voidscanReader(java.io.Reader r, java.lang.String inputName)

        if (r == null) {
            return;
        }

        if (reader != null) {
            clearScanner();
        }

        reader = r;
        this.inputName = inputName;
    
public intsetScope(int scope)

        int oldScope = currScope;
        currScope = scope;
        return oldScope;
    
private booleanskipSpaceAndComments()


         
        while(ch != CHAR_EOF) {
            if (whiteSpaceChars.indexOf(ch) != -1) {
                // continue
            } else if (scanCommentMulti && ch == '/" && peekNextChar() == '*") {
                getChar();
                
                while((ch = getChar()) != CHAR_EOF) {
                    if (ch == '*" && peekNextChar() == '/") {
                        getChar();
                        break;
                    }
                }

                if (ch == CHAR_EOF) {
                    return false;
                }
            } else if (commentSingle.length() == 2 && ch == commentSingle.charAt(0)) {
                while((ch = getChar()) != CHAR_EOF) {
                    if (ch == commentSingle.charAt(1)) {
                        break;
                    }
                }
                
                if (ch == CHAR_EOF) {
                    return false;
                }
            } else {
                break;
            }
            
            ch = getChar();
        }
        
        return true;
    
public voidunexpectedToken(int expected, java.lang.String symbolName, java.lang.String message, boolean isError)

        String prefix = "lexical error or unexpected token, expected valid token";

        if (message != null) {
            prefix += " - " + message;
        }

        printMessage(prefix, isError);