{
if( next_char2 == ':' )
{
advance();
advance();
return new token( sym.DBLCOLON );
}
else
{
advance();
return new token( sym.COLON );
}
}
/* leading L for wide strings */
if( next_char == 'L' && ( next_char2 =='\"' || next_char2 =='\'') )
{
wide = true;
advance();
if( next_char2 == '\"' )
{
advance();
in_string = true;
return new token( sym.LDBLQUOTE );
}
// wide char literal may follow, but detecting that
// is done below.
}
/* look for Shifts */
if( next_char == '<' )
{
if( next_char2 == '<' )
{
advance();
advance();
return new token( sym.LSHIFT );
}
else
{
advance();
return new token( sym.LESSTHAN );
}
}
if( next_char == '>' )
{
if( next_char2 == '>' )
{
advance();
advance();
return new token( sym.RSHIFT );
}
else
{
advance();
return new token( sym.GREATERTHAN );
}
}
/* leading 0: */
/* Try to scan octal/hexadecimal numbers, might even find a float */
if( next_char == '0' )
{
long l_val = 0;
long l_val_old = 0;
int radix = 8;
int digit = 0;
advance();
if( next_char == '.' )
{
StringBuffer f_string = new StringBuffer( "0." );
advance();
while( next_char >= '0' && next_char <= '9' )
{
f_string.append( (char)next_char );
advance();
}
float f_val = ( new Float( f_string.toString() ) ).floatValue();
return new float_token( sym.FLOAT_NUMBER, f_val );
}
else
{
// See if hexadecimal value
if( next_char == 'x' || next_char == 'X' )
{
advance();
radix = 16;
}
StringBuffer val = new StringBuffer( "0" );
digit = Character.digit( (char)next_char, radix );
while( digit != -1 )
{
val.append( (char)next_char );
advance();
digit = Character.digit( (char)next_char, radix );
}
String str = val.toString();
try
{
return new int_token( sym.NUMBER,
Integer.parseInt( str, radix ) );
}
catch( NumberFormatException ex )
{
try
{
return new long_token( sym.LONG_NUMBER,
Long.parseLong( str, radix ) );
}
catch( NumberFormatException ex2 )
{
emit_error( "Invalid octal/hex value: " + str );
}
}
return null;
}
}
/* Try to scan integer, floating point or fixed point literals */
if (isDigit (((char)next_char)) ||
next_char == '.' ||
(next_char == '-' && isDigit (((char)next_char2))))
{
StringBuffer value = new StringBuffer();
StringBuffer fraction = null;
int exp = 0;
if ( next_char == '-' )
{
value.append( (char)next_char );
advance();
}
// Read integer part
while( next_char >= '0' && next_char <= '9' )
{
value.append( (char)next_char );
advance();
}
// Read fraction
if( next_char == '.' )
{
fraction = new StringBuffer();
advance();
while( next_char >= '0' && next_char <= '9' )
{
fraction.append( (char)next_char );
advance();
}
}
// Read exponent
if( next_char == 'e' || next_char == 'E' )
{
if( fraction == null )
fraction = new StringBuffer();
fraction.append( 'e' );
advance();
if( next_char == '-' || next_char == '+' )
{
fraction.append( (char)next_char );
advance();
}
while( next_char >= '0' && next_char <= '9' )
{
fraction.append( (char)next_char );
advance();
}
if( fraction.length() == 1 )
{
emit_error( "Empty exponent in float/double." );
continue;
}
return new float_token( sym.FLOAT_NUMBER,
Float.valueOf( value.toString() +
"." +
fraction.toString() ).floatValue() );
}
if( next_char == 'd' || next_char == 'D' )
{
advance();
if( fraction == null )
fraction = new StringBuffer();
java.math.BigDecimal bi =
new java.math.BigDecimal( value.toString() + "." +
fraction.toString() );
return new fixed_token( sym.FIXED_NUMBER, bi );
}
if( fraction == null )
{
/* integer or long */
token tok = null;
String str = value.toString();
try
{
tok = new int_token( sym.NUMBER, Integer.parseInt( str ) );
}
catch( NumberFormatException ex )
{
try
{
tok = new long_token
( sym.LONG_NUMBER, Long.parseLong( str ) );
}
catch( NumberFormatException ex2 )
{
try
{
// Not quite critical yet - lets try stuffing it into
// a bigdecimal for later checking.
tok = new fixed_token
(sym.FIXED_NUMBER, new java.math.BigDecimal (str));
}
catch (NumberFormatException ex3)
{
emit_error( "Invalid long value: " + str );
}
}
}
return tok;
}
else
{
try
{
float f =
Float.valueOf( value.toString() + "." +
fraction.toString() ).floatValue();
return new float_token( sym.FLOAT_NUMBER, f );
}
catch( NumberFormatException nf )
{
emit_error( "Unexpected symbol: " +
value.toString() + "." +
fraction.toString() );
}
}
}
/* look for a single character symbol */
sym_num = find_single_char( next_char );
/* upon an opening double quote, return the
sym.DBLQUOTE token and continue scanning in the
in_string branch */
if( (char)next_char == '\"' )
{
in_string = true;
advance();
return new token( sym.DBLQUOTE );
}
if( (char)next_char == '\'' )
{
advance();
token t = null;
if( next_char == '\\' )
{
// Now need to process escaped character.
advance();
if( isDigit( (char)next_char ) )
{
// Octal character
char octal1 = '0';
char octal2 = '0';
char octal3 = (char)next_char;
if( isDigit( (char)next_char2 ) )
{
advance();
octal2 = octal3;
octal3 = (char)next_char;
if( isDigit( (char)next_char2 ) )
{
advance();
octal1 = octal2;
octal2 = octal3;
octal3 = (char)next_char;
}
}
t = new char_token
(
sym.CH,
(char)Integer.parseInt
( new String
( new char[]{octal1, octal2, octal3} ),
8
)
);
}
else if( (char)next_char == 'x' )
{
// Hexadecimal character
advance();
char hex1 = '0';
char hex2 = (char)next_char;
if( isHexLetterOrDigit( (char)next_char2 ) )
{
advance();
hex1 = hex2;
hex2 = (char)next_char;
}
else if( (char)next_char2 != '\'' )
{
emit_error( "Illegal hex character" );
return null;
}
t = new char_token
(
sym.CH,
(char)Integer.parseInt
( new String
( new char[]{hex1, hex2} ),
16
)
);
}
else if( (char)next_char == 'u' )
{
if( wide == false )
{
emit_error( "Unicode characters are only legal with wide character" );
return null;
}
else
{
// Hexadecimal character
advance();
char uni1 = '0';
char uni2 = '0';
char uni3 = '0';
char uni4 = (char)next_char;
if( isHexLetterOrDigit( (char)next_char2 ) )
{
advance();
uni3 = uni4;
uni4 = (char)next_char;
if( isHexLetterOrDigit( (char)next_char2 ) )
{
advance();
uni2 = uni3;
uni3 = uni4;
uni4 = (char)next_char;
if( isHexLetterOrDigit( (char)next_char2 ) )
{
advance();
uni1 = uni2;
uni2 = uni3;
uni3 = uni4;
uni4 = (char)next_char;
}
else if( (char)next_char2 != '\'' )
{
emit_error( "Illegal unicode character" );
return null;
}
}
else if( (char)next_char2 != '\'' )
{
emit_error( "Illegal unicode character" );
return null;
}
}
else if( (char)next_char2 != '\'' )
{
emit_error( "Illegal unicode character" );
return null;
}
t = new char_token
(
sym.CH,
(char)Integer.parseInt
( new String
( new char[]{uni1, uni2, uni3, uni4} ),
16
)
);
}
}
else
{
switch( next_char )
{
case 'n':
{
t = new char_token( sym.CH, '\n' );
break;
}
case 't':
{
t = new char_token( sym.CH, '\t' );
break;
}
case 'v':
{
t = new char_token( sym.CH, '\013' );
break;
}
case 'b':
{
t = new char_token( sym.CH, '\b' );
break;
}
case 'r':
{
t = new char_token( sym.CH, '\r' );
break;
}
case 'f':
{
t = new char_token( sym.CH, '\f' );
break;
}
case 'a':
{
t = new char_token( sym.CH, '\007' );
break;
}
case '\\':
{
t = new char_token( sym.CH, '\\' );
break;
}
case '?':
{
t = new char_token( sym.CH, '?' );
break;
}
case '0':
{
t = new char_token( sym.CH, '\0' );
break;
}
case '\'':
{
t = new char_token( sym.CH, '\'' );
break;
}
case '\"':
{
t = new char_token( sym.CH, '\"' );
break;
}
default:
{
emit_error( "Invalid escape symbol \'" );
return null;
}
}
}
}
else
{
t = new char_token( sym.CH, (char)next_char );
}
advance();
if( (char)next_char == '\'' )
{
tokenStack.push( new token( sym.QUOTE ) );
tokenStack.push( t );
advance();
}
else
{
emit_error( "Expecting closing \'" );
return null;
}
wide = false;
return new token( sym.QUOTE );
}
if( sym_num != -1 )
{
/* found one -- advance past it and return a token for it */
advance();
return new token( sym_num );
}
/* look for an id or keyword */
if( id_start_char( next_char ) )
{
token t = do_symbol();
if( t != null )
return t;
else
continue;
}
/* look for EOF */
if( next_char == EOF_CHAR )
{
return new token( sym.EOF );
}
}
else // in_string
{
/* empty string ? */
if( (char)next_char == '\"' )
{
in_string = false;
advance();
return new token( sym.DBLQUOTE );
}
StringBuffer result = new StringBuffer();
char previous = ' ';