/* * I expand macros on the form #name[arg1][arg2][arg] * where # can be any fixec char and [ ] can be changed * to any set of chars. * to get the char #, write ## * The name is a sequence of java.lang.Character.isLetterOrDogit * The left delimiter of the arguments must be a non-letter or digit. * It is permittable to have java.lang.Character.isWhitespace between the name * and arguments, as well as between args. */ package dk.itu.kasper.Macros; import java.io.Reader; import java.io.StringReader; import java.io.PrintStream; import java.io.IOException; import java.util.List; import java.util.ArrayList; import java.lang.reflect.Method; public class MacroProcessor { public final char macroChar = '#'; public final char leftChar = '['; public final char rightChar = ']'; private ReadIterator in; private PrintStream out; private MacroExpander expander; public MacroProcessor( Reader r , PrintStream p){ in = new ReadIterator( r ); out = p; } public MacroProcessor( String s, PrintStream p){ this( new StringReader( s ) , p); } public MacroProcessor( String s ){ this( s, System.out ); } public void setExpander(MacroExpander m){ expander = m; } public void process() throws IOException{ while ( in.hasMore() ) // current has not yet been written if ( in.current() != macroChar ) out.print( in.next() ); else{ in.next(); // skip macroChar if ( in.hasMore() && (in.current() != macroChar ) ) processMacro(); else{ in.next(); // skip macroChar out.print(macroChar); } } out.close(); } private void processMacro(){ String macroName = getName(); List args = getArgs(); out.print( expandMacro( macroName, args.subList(0,args.size()-1) ) ); out.print( args.get( args.size()-1 ) ); } private String getName(){ StringBuffer sb = new StringBuffer(); while( in.hasMore() && Character.isLetterOrDigit( in.current() ) ) sb.append( in.next() ); return sb.toString(); } private List getArgs(){ // Last argument is always whitespace following the arguments List ls = new ArrayList(); String whiteSpace = skipWhiteSpace(); while ( in.hasMore() && in.current() == leftChar ){ in.next(); ls.add( getArg() ); whiteSpace = skipWhiteSpace(); }; ls.add( whiteSpace ); return ls; } private String getArg(){ StringBuffer sb = new StringBuffer(); int level = 1; while (in.hasMore() && level > 0 ) { if ( in.current() == rightChar ) level--; else if ( in.current() == leftChar ) level++; if (level > 0) sb.append( in.current() ); in.next(); } return sb.toString(); } private String skipWhiteSpace(){ StringBuffer whiteSpace = new StringBuffer(); while (in.hasMore() && Character.isWhitespace( in.current() ) ) whiteSpace.append( in.next() ); if ( in.hasMore() && in.current() != leftChar ) return whiteSpace.toString(); else return ""; } public String expandMacro(String name, List args){ String[] sa = new String[ args.size() ]; sa = args.toArray( sa ); return expander.expand(name, sa ); } }