blob: 5fe7fbdb380d18f6288007626e39f1c3c1d7d7fd (
plain) (
tree)
|
|
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
\* */
// $Id$
package meta.util;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
/** A macro expander with support for indentation */
public class TextExpander {
//########################################################################
// Public Constants
/** Default macro name prefix */
public static final String MACRO_PREFIX = "print";
/** Default macro left quote */
public static final String MACRO_LQUOTE = "{#";
/** Default macro right quote */
public static final String MACRO_RQUOTE = "#}";
/** Do not edit warning */
public static final String DO_NOT_EDIT =
"DO NOT EDIT. Automatically generated file!";
//########################################################################
// Private Constants
/** An empty array of Classes */
private static final Class [] NO_PARAMS = new Class[0];
/** An empty array of Objects */
private static final Object[] NO_ARGS = new Object[0];
//########################################################################
// Private Fields
/** The output text writer */
private final TextWriter writer;
/** The macro expander */
private final Object expander;
/** The current macro name prefix */
private String prefix;
/** The current macro left quote */
private String lquote;
/** The current macro right quote */
private String rquote;
/** The current input name */
private String name;
/** The current input line number */
private int line;
/** The current error count */
private int errors;
//########################################################################
// Public Constructors
/** Creates a new TextExpander. */
public TextExpander(TextWriter writer, Object expander) {
this.writer = writer;
this.expander = expander;
this.prefix = MACRO_PREFIX;
this.lquote = MACRO_LQUOTE;
this.rquote = MACRO_RQUOTE;
}
//########################################################################
// Public Methods - Text expansion
/** Expands the text from the given file. */
public void expandText(File file) {
setInputName(file.toString());
setInputLine(0);
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
expandText(reader);
reader.close();
} catch (IOException exception) {
error("input error", exception);
}
}
/** Expands the text from the given character stream. */
public void expandText(BufferedReader reader) {
try {
for (String line; (line = reader.readLine()) != null;) {
this.line++;
expandLine(line);
}
} catch (IOException exception) {
error("input error", exception);
}
}
/** Expands the given line. */
public void expandLine(String line) {
int index = 0;
int column = 0;
for (; index < line.length(); index++) {
switch (line.charAt(index)) {
case ' ' : column += 1; continue;
case '\t': column += 8 - (column % 8); continue;
}
break;
}
if (index < line.length()) {
int width = writer.getIndentWidth();
writer.setIndentLevel(column / width);
for (int i = 0; i < column % width; i++) writer.print(' ');
line = line.substring(index);
if (line.indexOf("$Id") >= 0)
line = line.replaceFirst("[$]Id.*[$]", DO_NOT_EDIT);
expand(line);
}
writer.println();
}
/** Expands the given string. */
public void expand(String input) {
int start = 0;
while (true) {
int lindex = input.indexOf(lquote, start);
if (lindex < 0) break;
int rindex = input.indexOf(rquote, lindex + lquote.length());
if (rindex < 0) { error("unclosed macro"); break; }
String macro = input.substring(lindex + lquote.length(), rindex);
if (macro.indexOf(lquote) >= 0) { error("unclosed macro"); break; }
if (start < lindex) writer.print(input.substring(start, lindex));
expandMacro(macro);
start = rindex + rquote.length();
}
if (start < input.length()) writer.print(input.substring(start));
}
//########################################################################
// Public Methods - Macro expansion
/** Expands the given macro. */
public void expandMacro(String macro) {
String member = prefix + macro;
Class clasz = expander.getClass();
try {
expandMacro(macro, clasz.getMethod(member, NO_PARAMS));
} catch (NoSuchMethodException exception) {
error("macro '" + macro + "' is undefined");
writer.print(lquote + macro + rquote);
}
}
/** Expands the given macro by invoking the given method. */
public void expandMacro(String macro, Method method) {
try {
method.invoke(expander, NO_ARGS);
} catch (IllegalAccessException exception) {
error("macro '" + macro + "' could not access method " + method);
writer.print(lquote + macro + rquote);
} catch (InvocationTargetException exception) {
error("macro '" + macro + "' raised an exception");
exception.getTargetException().printStackTrace();
}
}
//########################################################################
// Public Methods - Error messages
/** Prints an error message. */
public void error(String error) {
String prefix = name != null ? name + ":" : "error:";
if (line > 0) prefix = prefix + line + ":";
System.err.println(prefix + " " + error);
errors++;
}
/** Prints an error message. */
public void error(String error, Throwable exception) {
if (exception.getMessage() != null)
error(exception.getMessage());
else
error(error + " (" + exception.getClass().getName() + ")");
}
//########################################################################
// Public Methods - Getters
/** Returns the output text writer. */
public TextWriter getOutputWriter() {
return writer;
}
/** Returns the macro expander. */
public Object getMacroExpander() {
return expander;
}
/** Returns the current macro name prefix. */
public String getMacroPrefix() {
return prefix;
}
/** Returns the current macro left quote. */
public String getMacroLeftQuote() {
return lquote;
}
/** Returns the current macro right quote. */
public String getMacroRightQuote() {
return lquote;
}
/** Returns the current input name. */
public String getInputName() {
return name;
}
/** Returns the current input line. */
public int getInputLine() {
return line;
}
/** Returns the current error count. */
public int getErrorCount() {
return errors;
}
//########################################################################
// Public Methods - Setters
/** Sets the current macro name prefix. */
public void setMacroPrefix(String prefix) {
this.prefix = prefix;
}
/** Sets the current macro quotes. */
public void setMacroQuotes(String lquote, String rquote) {
this.lquote = lquote;
this.rquote = rquote;
}
/** Sets the current input name. */
public void setInputName(String name) {
this.name = name;
}
/** Sets the current input line. */
public void setInputLine(int line) {
this.line = line;
}
/** Sets the current error count. */
public void setErrorCount(int errors) {
this.errors = errors;
}
//########################################################################
}
|