|
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.