javassist.compiler.Lex Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist.compiler;
class Token {
public Token next = null;
public int tokenId;
public long longValue;
public double doubleValue;
public String textValue;
}
public class Lex implements TokenId {
private int lastChar;
private StringBuffer textBuffer;
private Token currentToken;
private Token lookAheadTokens;
private String input;
private int position, maxlen, lineNumber;
/**
* Constructs a lexical analyzer.
*/
public Lex(String s) {
lastChar = -1;
textBuffer = new StringBuffer();
currentToken = new Token();
lookAheadTokens = null;
input = s;
position = 0;
maxlen = s.length();
lineNumber = 0;
}
public int get() {
if (lookAheadTokens == null)
return get(currentToken);
else {
Token t;
currentToken = t = lookAheadTokens;
lookAheadTokens = lookAheadTokens.next;
return t.tokenId;
}
}
/**
* Looks at the next token.
*/
public int lookAhead() {
return lookAhead(0);
}
public int lookAhead(int i) {
Token tk = lookAheadTokens;
if (tk == null) {
lookAheadTokens = tk = currentToken; // reuse an object!
tk.next = null;
get(tk);
}
for (; i-- > 0; tk = tk.next)
if (tk.next == null) {
Token tk2;
tk.next = tk2 = new Token();
get(tk2);
}
currentToken = tk;
return tk.tokenId;
}
public String getString() {
return currentToken.textValue;
}
public long getLong() {
return currentToken.longValue;
}
public double getDouble() {
return currentToken.doubleValue;
}
private int get(Token token) {
int t;
do {
t = readLine(token);
} while (t == '\n');
token.tokenId = t;
return t;
}
private int readLine(Token token) {
int c = getNextNonWhiteChar();
if(c < 0)
return c;
else if(c == '\n') {
++lineNumber;
return '\n';
}
else if (c == '\'')
return readCharConst(token);
else if (c == '"')
return readStringL(token);
else if ('0' <= c && c <= '9')
return readNumber(c, token);
else if(c == '.'){
c = getc();
if ('0' <= c && c <= '9') {
StringBuffer tbuf = textBuffer;
tbuf.setLength(0);
tbuf.append('.');
return readDouble(tbuf, c, token);
}
else{
ungetc(c);
return readSeparator('.');
}
}
else if (Character.isJavaIdentifierStart((char)c))
return readIdentifier(c, token);
else
return readSeparator(c);
}
private int getNextNonWhiteChar() {
int c;
do {
c = getc();
if (c == '/') {
c = getc();
if (c == '/')
do {
c = getc();
} while (c != '\n' && c != '\r' && c != -1);
else if (c == '*')
while (true) {
c = getc();
if (c == -1)
break;
else if (c == '*')
if ((c = getc()) == '/') {
c = ' ';
break;
}
else
ungetc(c);
}
else {
ungetc(c);
c = '/';
}
}
} while(isBlank(c));
return c;
}
private int readCharConst(Token token) {
int c;
int value = 0;
while ((c = getc()) != '\'')
if (c == '\\')
value = readEscapeChar();
else if (c < 0x20) {
if (c == '\n')
++lineNumber;
return BadToken;
}
else
value = c;
token.longValue = value;
return CharConstant;
}
private int readEscapeChar() {
int c = getc();
if (c == 'n')
c = '\n';
else if (c == 't')
c = '\t';
else if (c == 'r')
c = '\r';
else if (c == 'f')
c = '\f';
else if (c == '\n')
++lineNumber;
return c;
}
private int readStringL(Token token) {
int c;
StringBuffer tbuf = textBuffer;
tbuf.setLength(0);
for (;;) {
while ((c = getc()) != '"') {
if (c == '\\')
c = readEscapeChar();
else if (c == '\n' || c < 0) {
++lineNumber;
return BadToken;
}
tbuf.append((char)c);
}
for (;;) {
c = getc();
if (c == '\n')
++lineNumber;
else if (!isBlank(c))
break;
}
if (c != '"') {
ungetc(c);
break;
}
}
token.textValue = tbuf.toString();
return StringL;
}
private int readNumber(int c, Token token) {
long value = 0;
int c2 = getc();
if (c == '0')
if (c2 == 'X' || c2 == 'x')
for (;;) {
c = getc();
if ('0' <= c && c <= '9')
value = value * 16 + (long)(c - '0');
else if ('A' <= c && c <= 'F')
value = value * 16 + (long)(c - 'A' + 10);
else if ('a' <= c && c <= 'f')
value = value * 16 + (long)(c - 'a' + 10);
else {
token.longValue = value;
if (c == 'L' || c == 'l')
return LongConstant;
else {
ungetc(c);
return IntConstant;
}
}
}
else if ('0' <= c2 && c2 <= '7') {
value = c2 - '0';
for (;;) {
c = getc();
if ('0' <= c && c <= '7')
value = value * 8 + (long)(c - '0');
else {
token.longValue = value;
if (c == 'L' || c == 'l')
return LongConstant;
else {
ungetc(c);
return IntConstant;
}
}
}
}
value = c - '0';
while ('0' <= c2 && c2 <= '9') {
value = value * 10 + c2 - '0';
c2 = getc();
}
token.longValue = value;
if (c2 == 'F' || c2 == 'f') {
token.doubleValue = (double)value;
return FloatConstant;
}
else if (c2 == 'E' || c2 == 'e'
|| c2 == 'D' || c2 == 'd' || c2 == '.') {
StringBuffer tbuf = textBuffer;
tbuf.setLength(0);
tbuf.append(value);
return readDouble(tbuf, c2, token);
}
else if (c2 == 'L' || c2 == 'l')
return LongConstant;
else {
ungetc(c2);
return IntConstant;
}
}
private int readDouble(StringBuffer sbuf, int c, Token token) {
if (c != 'E' && c != 'e' && c != 'D' && c != 'd') {
sbuf.append((char)c);
for (;;) {
c = getc();
if ('0' <= c && c <= '9')
sbuf.append((char)c);
else
break;
}
}
if (c == 'E' || c == 'e') {
sbuf.append((char)c);
c = getc();
if (c == '+' || c == '-') {
sbuf.append((char)c);
c = getc();
}
while ('0' <= c && c <= '9') {
sbuf.append((char)c);
c = getc();
}
}
try {
token.doubleValue = Double.parseDouble(sbuf.toString());
}
catch (NumberFormatException e) {
return BadToken;
}
if (c == 'F' || c == 'f')
return FloatConstant;
else {
if (c != 'D' && c != 'd')
ungetc(c);
return DoubleConstant;
}
}
// !"#$%&'( )*+,-./0 12345678 9:;<=>?
private static final int[] equalOps
= { NEQ, 0, 0, 0, MOD_E, AND_E, 0, 0,
0, MUL_E, PLUS_E, 0, MINUS_E, 0, DIV_E, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, LE, EQ, GE, 0 };
private int readSeparator(int c) {
int c2, c3;
if ('!' <= c && c <= '?') {
int t = equalOps[c - '!'];
if (t == 0)
return c;
else {
c2 = getc();
if (c == c2)
switch (c) {
case '=' :
return EQ;
case '+' :
return PLUSPLUS;
case '-' :
return MINUSMINUS;
case '&' :
return ANDAND;
case '<' :
c3 = getc();
if (c3 == '=')
return LSHIFT_E;
else {
ungetc(c3);
return LSHIFT;
}
case '>' :
c3 = getc();
if (c3 == '=')
return RSHIFT_E;
else if (c3 == '>') {
c3 = getc();
if (c3 == '=')
return ARSHIFT_E;
else {
ungetc(c3);
return ARSHIFT;
}
}
else {
ungetc(c3);
return RSHIFT;
}
default :
break;
}
else if (c2 == '=')
return t;
}
}
else if (c == '^') {
c2 = getc();
if (c2 == '=')
return EXOR_E;
}
else if (c == '|') {
c2 = getc();
if (c2 == '=')
return OR_E;
else if (c2 == '|')
return OROR;
}
else
return c;
ungetc(c2);
return c;
}
private int readIdentifier(int c, Token token) {
StringBuffer tbuf = textBuffer;
tbuf.setLength(0);
do {
tbuf.append((char)c);
c = getc();
} while (Character.isJavaIdentifierPart((char)c));
ungetc(c);
String name = tbuf.toString();
int t = ktable.lookup(name);
if (t >= 0)
return t;
else {
/* tbuf.toString() is executed quickly since it does not
* need memory copy. Using a hand-written extensible
* byte-array class instead of StringBuffer is not a good idea
* for execution speed. Converting a byte array to a String
* object is very slow. Using an extensible char array
* might be OK.
*/
token.textValue = name;
return Identifier;
}
}
private static final KeywordTable ktable = new KeywordTable();
static {
ktable.append("abstract", ABSTRACT);
ktable.append("boolean", BOOLEAN);
ktable.append("break", BREAK);
ktable.append("byte", BYTE);
ktable.append("case", CASE);
ktable.append("catch", CATCH);
ktable.append("char", CHAR);
ktable.append("class", CLASS);
ktable.append("const", CONST);
ktable.append("continue", CONTINUE);
ktable.append("default", DEFAULT);
ktable.append("do", DO);
ktable.append("double", DOUBLE);
ktable.append("else", ELSE);
ktable.append("extends", EXTENDS);
ktable.append("false", FALSE);
ktable.append("final", FINAL);
ktable.append("finally", FINALLY);
ktable.append("float", FLOAT);
ktable.append("for", FOR);
ktable.append("goto", GOTO);
ktable.append("if", IF);
ktable.append("implements", IMPLEMENTS);
ktable.append("import", IMPORT);
ktable.append("instanceof", INSTANCEOF);
ktable.append("int", INT);
ktable.append("interface", INTERFACE);
ktable.append("long", LONG);
ktable.append("native", NATIVE);
ktable.append("new", NEW);
ktable.append("null", NULL);
ktable.append("package", PACKAGE);
ktable.append("private", PRIVATE);
ktable.append("protected", PROTECTED);
ktable.append("public", PUBLIC);
ktable.append("return", RETURN);
ktable.append("short", SHORT);
ktable.append("static", STATIC);
ktable.append("strictfp", STRICT);
ktable.append("super", SUPER);
ktable.append("switch", SWITCH);
ktable.append("synchronized", SYNCHRONIZED);
ktable.append("this", THIS);
ktable.append("throw", THROW);
ktable.append("throws", THROWS);
ktable.append("transient", TRANSIENT);
ktable.append("true", TRUE);
ktable.append("try", TRY);
ktable.append("void", VOID);
ktable.append("volatile", VOLATILE);
ktable.append("while", WHILE);
}
private static boolean isBlank(int c) {
return c == ' ' || c == '\t' || c == '\f' || c == '\r'
|| c == '\n';
}
private static boolean isDigit(int c) {
return '0' <= c && c <= '9';
}
private void ungetc(int c) {
lastChar = c;
}
public String getTextAround() {
int begin = position - 10;
if (begin < 0)
begin = 0;
int end = position + 10;
if (end > maxlen)
end = maxlen;
return input.substring(begin, end);
}
private int getc() {
if (lastChar < 0)
if (position < maxlen)
return input.charAt(position++);
else
return -1;
else {
int c = lastChar;
lastChar = -1;
return c;
}
}
}