|
What this is
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.mdrshell;
import java.util.*;
import java.io.*;
/** Implements the #define and #include commands well known from C/C++
*
* @author Petr Hrebejk
* @version
*/
public class Preprocessor extends Object {
/** #deinfe / #include command delimiters */
private static final String DELIMITERS = " ";
private static final char HASH ='#';
private static final char BACK_QUOTE = '`';
private static final String DEFINE = "#define";
private static final String INCLUDE = "#include";
private static final String UNDEFINE = "#undef";
private static final String PARAMS = "[$]";
/** Variables defined in this shell */
Hashtable definedVariables;
/** Parametrized variables (commands) in this shell */
Hashtable definedParamVariables;
/** The shell this preprocessor works for */
private Shell shell;
/** Creates new CommandPerformer
*/
Preprocessor( Shell shell ) {
definedVariables = new Hashtable( 11 );
definedParamVariables = new Hashtable( 11 );
this.shell = shell;
}
/** Recognizes the commands and replaces predefined variables
*/
String processLine( String line ) throws PreprocessorException {
if ( processCommand( line ) ) {
return null;
}
String processedLine = replaceVariables( line );
return processedLine;
}
// Private methods ---------------------------------------------------------
boolean processCommand( String line ) throws PreprocessorException {
if ( line.charAt( 0 ) != HASH ) {
return false;
}
StringTokenizer st = new StringTokenizer( line, DELIMITERS );
int tokenCount = st.countTokens();
if ( tokenCount == 0 ) {
return false;
}
String command = st.nextToken();
if ( command.equals( DEFINE ) ) { // Handle the #define command
if ( tokenCount < 2 ) {
throw new PreprocessorException( "Variable not specified: " + line );
}
String variable = st.nextToken();
String value = tokenCount == 2 ? "" : st.nextToken( "" ).trim();
VariableDescriptor vd = new VariableDescriptor( variable, value );
definedVariables.put( vd.getName(), vd );
return true;
}
else if ( command.equals( UNDEFINE ) ) { // Handle the #undef command
if ( tokenCount != 2 ) {
throw new PreprocessorException( "Variable not specified: " + line );
}
String variable = st.nextToken();
if ( definedVariables.get( variable ) == null ) {
throw new PreprocessorException( "Variable " + variable + " not defined: " + line );
}
definedVariables.remove( variable );
return true;
}
else if ( command.equals( INCLUDE ) ) { // Handle #include command
if ( tokenCount == 1 ) {
throw new PreprocessorException( "File not specified: " + line );
}
String fileName = st.nextToken( );
File file = new File( fileName );
try {
InputStream is = new FileInputStream( fileName );
shell.pushInput( is );
}
catch ( java.io.FileNotFoundException e ) {
throw new PreprocessorException( "File " + fileName + " not found: " + line );
}
return true;
}
else {
return false;
}
}
/** Replaces the variables in given string.
*/
private String replaceVariables( String line ) throws PreprocessorException {
ArrayList tokens = tokenize( line ); // Get tokenized form of the line
//printTokens( tokens );
while( replaceVariables( tokens) ); // Replace variables until no is found
// Now we need to find and remove all tokens which are just BACK_QUOTES
for( Iterator it = tokens.iterator(); it.hasNext(); ) {
Token t = (Token)it.next();
if ( t.ttype == BACK_QUOTE ) {
it.remove();
}
}
return restoreString( tokens );
}
/** Replaces variables in tokenized string. Starts at startIndex
*/
private boolean replaceVariables( ArrayList tokens ) {
for ( int i = tokens.size() - 1; i >= 0; i-- ) { // For all tokens from right to left
Token t = (Token)tokens.get(i);
if ( t.ttype != StreamTokenizer.TT_WORD ) // Skip whitespaces and separators
continue;
// Test wether token equals to some variable
Collection vars = definedVariables.keySet();
for( Iterator it = vars.iterator(); it.hasNext(); ) { // For all variables
String variableName = (String)it.next();
if ( t.sval.equals( variableName ) ) {
// Variable found replace it
replaceVariable( tokens, variableName, i );
return true;
}
}
}
return false;
}
/** Replaces the variable in the tokeized string
*/
private void replaceVariable( ArrayList tokens, String variable, int index ) {
VariableDescriptor vd = (VariableDescriptor)definedVariables.get( variable );
tokens.remove( index ); // Removes the token with the variable
ArrayList params = vd.extractParameters( tokens, index ); // Extract params and remove the tokens
String variableValue = vd.getValue();
if ( vd.isParam() ) { // We have replace the $n with param values in the variable value
for( int i = vd.getParamCount(); i > 0 ; i-- ) { // For all params
String paramName = "$" + i;
while( variableValue.indexOf( paramName ) != -1 ) { // For all occurences of the param
variableValue = replaceString( variableValue, paramName, (String)params.get( i - 1 ) );
}
}
}
ArrayList tv = tokenize( variableValue );
if ( index >= tokens.size() ) {
tokens.addAll( tv );
}
else {
tokens.addAll( index, tv );
}
}
/** Parses a string to collection of tokens
*/
private ArrayList tokenize( String line ) {
ArrayList tokens = new ArrayList( 100 );
StreamTokenizer stok = new StreamTokenizer( new StringReader( line ) );
stok.resetSyntax();
// Initialize the Stream tokenizer to standard Java except of parsing numbers
stok.wordChars('a', 'z');
stok.wordChars('A', 'Z');
stok.wordChars(128 + 32, 255);
//stok.whitespaceChars(0, ' ');
stok.commentChar('/');
stok.quoteChar('"');
stok.quoteChar('\'');
// Changes to standard Java
// if ( quotas ) {
// stok.quoteChar('`'); // This quote means that the wohle token should be taken as
// command parameter.
//}
//stok.quoteChar('~'); // Tilda means execute command and put result as string into command
stok.wordChars('$', '$'); // Command parameters
stok.wordChars('_', '_'); // Underlines are part of identifiers
stok.wordChars('0', '9'); // Take numbers as part of words
stok.ordinaryChars(0, ' '); // We want to know about spaces
stok.ordinaryChar(BACK_QUOTE); // We want to know about spaces
try {
while ( stok.nextToken() != StreamTokenizer.TT_EOF ) {
tokens.add( new Token( stok.sval, stok.ttype ) );
}
}
catch ( java.io.IOException e ) {
}
return tokens;
}
/** ReCreates a string from collection of tokens
*/
private String restoreString( ArrayList tokens ) {
StringBuffer sb = new StringBuffer( 200 );
for ( Iterator it = tokens.iterator(); it.hasNext(); ) {
Token token = (Token)it.next();
if ( token.sval == null ) {
sb.append( (char)token.ttype );
}
else if ( token.ttype < 0 ) {
sb.append( token.sval );
}
else {
sb.append( (char)token.ttype );
sb.append( token.sval );
sb.append( (char)token.ttype );
}
}
return sb.toString();
}
private String replaceString( String in, String what, String by ) {
StringBuffer sb = new StringBuffer( in );
int index = in.indexOf( what );
sb.delete( index, index + what.length() );
sb.insert( index, by );
return sb.toString();
}
// Innerclasses ------------------------------------------------------------
/** Description of a defined variable
*/
private class VariableDescriptor extends Object {
private String name;
private String value;
private boolean isParam;
private int paramCount;
VariableDescriptor( String var, String value ) {
if ( var.endsWith( PARAMS ) ) {
name = var.substring(0, var.length() - PARAMS.length() );
isParam = true;
for ( int i = 1; true; i++ ) {
String pname = "$" + i;
if ( value.indexOf( pname ) == -1 ) {
paramCount = i - 1;
break;
}
}
}
else {
name = var;
isParam = false;
}
this.value = value;
}
String getName() {
return name;
}
String getValue() {
return value;
}
boolean isParam() {
return isParam;
}
int getParamCount() {
return paramCount;
}
/** Returns collection of strings representing the command parameters. The original
* tokens are removed from the tokens list.
*/
ArrayList extractParameters( ArrayList tokens, int index ) {
if ( !isParam() ) {
return null;
}
ArrayList parameters = new ArrayList( getParamCount() );
Token t = (Token)tokens.get( index );
for ( int i = 0; i < getParamCount(); i++ ) { // For all parameters
try {
while( t.ttype >= 0 && t.ttype <= 32 ) { // Remove trailing spaces
tokens.remove( index );
t = (Token)tokens.get( index );
}
StringBuffer sb = new StringBuffer( "" );
boolean isQuoted = false;
if ( t.ttype == BACK_QUOTE ) {
isQuoted = true;
tokens.remove( index );
t = (Token)tokens.get( index );
}
while( true ) {
if ( (t.ttype >= 0 && t.ttype <= 32) || t.ttype == BACK_QUOTE ) {
if ( isQuoted && t.ttype == BACK_QUOTE ) {
tokens.remove( index );
break;
}
else if ( !isQuoted ) {
break;
}
}
if ( t.sval == null ) {
sb.append( (char)t.ttype );
}
else if ( t.ttype < 0 ) {
sb.append( t.sval );
}
else {
sb.append( (char)t.ttype );
sb.append( t.sval );
sb.append( (char)t.ttype );
}
tokens.remove( index );
if ( index >= tokens.size() ) {
break;
}
t = (Token)tokens.get( index );
}
parameters.add( sb.toString() );
}
catch( IndexOutOfBoundsException e ) {
parameters.add( "null" );
}
}
return parameters;
}
}
/** Token in a parsed string
*/
private static class Token {
String sval;
int ttype;
Token( String value, int type ) {
sval = value;
ttype = type;
}
public String toString() {
return "[ " + sval + ", " + ttype + " ]";
}
}
void printTokens( ArrayList tokens ) {
System.out.print( "{ ");
for( Iterator it = tokens.iterator(); it.hasNext(); ) {
System.out.print( it.next() + ", ");
}
System.out.println(" }");
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.