import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
/**
* Implements a <em>temporary variables pool</em>, providing methods to
* retrieve free variables from the pool, reset the pool and generate
* Java declarations for the variables.
*
* @layer<bali2javacc>
*/
public class Variables {
final public String LOWER = "abcdefghijklmnopqrstuvwxyz" ;
final public String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
public Variables() {
this.declarations = new ArrayList() ;
this.prefixSet = new HashSet() ;
this.random = new Random( 0L ) ;
this.typeMap = new TreeMap() ;
this.usedSet = new HashSet() ;
}
public String declare( String type, String name, String value ) {
declarations.add( type + ' ' + name + " = " + value ) ;
return name ;
}
public String getFree( String type ) {
TypeData data = ( TypeData ) typeMap.get( type ) ;
if ( data == null ) {
data = new TypeData( type ) ;
typeMap.put( type, data ) ;
}
String variable = data.prefix + data.count ;
data.limit = Math.max( data.limit, ++data.count ) ;
return variable ;
}
public String randomChars() {
char one = UPPER.charAt( random.nextInt( UPPER.length() ) ) ;
char two = LOWER.charAt( random.nextInt( LOWER.length() ) ) ;
return new String( new char[] {one, two} ) ;
}
/**
* Frees all the variables currently in use in this pool.
*
* @layer<bali2javacc>
*/
public void reset() {
for ( Iterator p = typeMap.values().iterator() ; p.hasNext() ; ) {
TypeData data = ( TypeData ) p.next() ;
data.count = 0 ;
}
}
/**
* Returns a String of Java declarations for the variables in the pool.
*
* @layer<bali2javacc>
*/
public String toString() {
StringBuffer buffer = new StringBuffer() ;
Collections.sort( declarations ) ;
for ( Iterator p = declarations.iterator() ; p.hasNext() ; ) {
if ( buffer.length() > 0 )
buffer.append( Main.LINE_SEPARATOR ) ;
buffer.append( p.next().toString() ) ;
buffer.append( " ;" ) ;
}
for ( Iterator p = typeMap.entrySet().iterator() ; p.hasNext() ; ) {
Map.Entry entry = ( Map.Entry ) p.next() ;
String type = ( String ) entry.getKey() ;
TypeData data = ( TypeData ) entry.getValue() ;
if ( buffer.length() > 0 )
buffer.append( Main.LINE_SEPARATOR ) ;
buffer.append( type ) ;
buffer.append( ' ' ) ;
for ( int n = data.limit ; --n > 0 ; )
buffer.append( data.prefix + n + "=null, " ) ;
buffer.append( data.prefix + "0=null ;" ) ;
}
return buffer.toString() ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
final private List declarations ;
final private Set prefixSet ;
final private Random random ;
final private Map typeMap ;
final private Set usedSet ;
final public class TypeData {
TypeData( String type ) {
String leader = type.substring( 0,2 ).toLowerCase() ;
String prefix = leader ;
while ( prefixSet.contains( prefix ) )
prefix = leader + randomChars() ;
prefixSet.add( prefix ) ;
this.count = 0 ;
this.limit = 0 ;
this.prefix = prefix ;
}
public int count ;
public int limit ;
public String prefix ;
}
}