// $Id$
import java.io.*;
public class verbfilterScala {
static String[] reserved = {
"abstract", "case", "catch", "class", "def",
"do", "else", "extends", "false", "final",
"finally", "for", "if", "import", "new",
"null", "object", "override", "package", "private",
"protected", "requires", "return", "sealed", "super", "this", "throw",
"trait", "true", "try", "type", "val",
"var", "while", "with", "yield"};
static final int TABINC = 8;
final static String beginVerbatim = "\\begin{verbatim}";
final static String endVerbatim = "\\end{verbatim}";
final static String verb = "\\verb";
static int lineCount, verbLine;
static boolean startsWith(byte[] buf, int offset, String s) {
int i = 0;
while (i < s.length() && buf[offset+i] == s.charAt(i)) i++;
return i == s.length();
}
static void writeString(OutputStream out, String s) throws IOException {
for (int i = 0; i < s.length(); i++)
out.write(s.charAt(i));
}
static int skipBlanks(byte[] buf, int offset) {
while (buf[offset] == ' ') offset++;
return offset;
}
static int compare(byte[] buf, int i, String key) {
int j = 0;
int l = key.length();
while (i < buf.length && j < l) {
char bch = (char)buf[i];
char kch = key.charAt(j);
if (bch < kch) return -1;
else if (bch > kch) return 1;
i++;
j++;
}
if (j < l)
return -1;
else if (i < buf.length &&
('A' <= buf[i] && buf[i] <= 'Z' ||
'a' <= buf[i] && buf[i] <= 'z' ||
'0' <= buf[i] && buf[i] <= '9' ||
buf[i] == '_'))
return 1;
else
return 0;
}
static int keyIndex(byte[] buf, int i, String[] keys) {
int lo = 0;
int hi = keys.length - 1;
while (lo <= hi) {
int mid = (hi + lo) / 2;
int diff = compare(buf, i, keys[mid]);
if (diff < 0) hi = mid - 1;
else if (diff > 0) lo = mid + 1;
else return mid;
}
return -1;
}
static int processLeadingWhitespace(byte[] buf,
int i,
OutputStream out) throws IOException {
int col = 0;
while (true) {
if (buf[i] == ' ') {
writeString(out, "~~"); i++; col++;
} else if (buf[i] == '\t') {
i++;
do {
writeString(out, "~~"); col++;
} while (col % TABINC != 0);
} else {
return i;
}
}
}
static int processVerbatim(byte[] buf,
int i,
OutputStream out,
String delimiter) throws IOException {
verbLine = lineCount;
int delimiter0 = delimiter.charAt(0);
int j = skipBlanks(buf, i);
if (buf[j] == '\n') { i = j+1; lineCount++; }
i = processLeadingWhitespace(buf, i, out);
while (true) {
if (buf[i] == delimiter0 && startsWith(buf, i, delimiter))
return i + delimiter.length();
switch (buf[i]) {
case ' ':
writeString(out, "~");
break;
case '\n':
writeString(out, "\n");
j = i+1;
lineCount++;
if (buf[j] == delimiter0 && startsWith(buf, j, delimiter))
return j + delimiter.length();
writeString(out, "\\\\");
if (buf[i+1] == '\n') {
writeString(out, "[0.5em]"); i++;
lineCount++;
}
i = processLeadingWhitespace(buf, i+1, out)-1;
break;
case '^':
writeString(out, "\\^~$\\!\\!$");
break;
case '&':
writeString(out, "\\&");
break;
case '*':
writeString(out, "$*$");
break;
case '%':
writeString(out, "$\\%$");
break;
case '_':
writeString(out, "\\_");
break;
case '~':
writeString(out, "\\~~$\\!\\!$");
break;
case '{':
writeString(out, "{\\small\\{}");
break;
case '}':
writeString(out, "{\\small\\}}");
break;
case '[':
writeString(out, "$[$");
//if (buf[i+1] == ']') out.write('~');
break;
case ']':
writeString(out, "$]$");
break;
case '(':
writeString(out, "$($");
break;
case ')':
writeString(out, "$)$");
break;
case ':':
if (i > 0 && Character.isJavaIdentifierPart((char)buf[i-1]))
writeString(out, "\\,");
writeString(out, "{\\rm :}");
break;
case '<':
if (buf[i+1] == '=') {
writeString(out, "$\\leq$"); i++;
} else if (buf[i+1] == '-') {
writeString(out, "$\\leftarrow$"); i++;
} else if (buf[i+1] == '<') {
writeString(out, "$<\\!$");
} else {
writeString(out, "$<$");
}
break;
case '>':
if (buf[i+1] == '=') {
writeString(out, "$\\geq$"); i++;
} else if (buf[i+1] == '>') {
writeString(out, "$>\\!$");
} else {
writeString(out, "$>$");
}
break;
case '=':
if (buf[i+1] == '=') {
writeString(out, "$==$"); i++;
} else if (buf[i+1] == '>') {
writeString(out, "$\\Rightarrow$"); i++;
} else {
out.write('=');
}
break;
case '/':
if (buf[i+1] == '/') {
out.write ('/');
do {
out.write(buf[i+1]);
i++;
} while (buf[i+1] != '\n' &&
(buf[i+1] != delimiter0 ||
!startsWith(buf, i+1, delimiter)));
} else {
out.write('/');
}
break;
case '-':
if (buf[i+1] == '>') {
writeString(out, "$\\rightarrow$");
i++;
} else {
writeString(out, "$-$");
}
break;
case '+':
writeString(out, "$+$");
break;
case '|':
writeString(out, "$\\,|$");
break;
case '#':
writeString(out, "\\#");
break;
case '\\':
if (buf[i+1] == '=' || buf[i+1] == '>') {
out.write(buf[i]);
i++;
out.write(buf[i]);
} else if (buf[i+1] == '$') {
writeString(out, "\\$");
i++;
} else if (buf[i+1] == 'R') {
writeString(out, "\\color{red}"); i++;
} else if (buf[i+1] == 'S') {
writeString(out, "\\color{black}"); i++;
} else if (buf[i+1] == 'B') {
writeString(out, "\\color{blue}"); i++;
} else if (buf[i+1] == 'G') {
writeString(out, "\\color{green}"); i++;
} else {
writeString(out, "$\\backslash$");
}
break;
case '$':
out.write(buf[i]);
do {
i++;
out.write(buf[i]);
} while (i + 1 < buf.length && buf[i] != '$');
break;
default:
if (i == 0 || !Character.isJavaIdentifierPart((char)buf[i-1])) {
int k = keyIndex(buf, i, reserved);
if (k >= 0) {
writeString(out, "{\\vem " + reserved[k] + "}");
i = i + reserved[k].length() - 1;
break;
}
}
out.write(buf[i]);
break;
}
i++;
}
}
static void process(byte[] buf, OutputStream out) throws IOException {
int i = 0;
while (i < buf.length - 1) {
if (buf[i] == '%') {
do {
out.write(buf[i]);
i++;
} while (buf[i] != '\n' && buf[i] != 0);
} else if (startsWith(buf, i, beginVerbatim)) {
writeString(out, "\\begin{program}");
i = processVerbatim(buf, i + beginVerbatim.length(), out,
endVerbatim);
writeString(out, "\\end{program}");
} else if (startsWith(buf, i, verb)) {
writeString(out, "\\prog{");
i = i + verb.length();
char[] delimiterArray = {(char)buf[i]};
String delimiter = new String(delimiterArray);
i = processVerbatim(buf, i + 1, out, delimiter);
writeString(out, "}");
} else {
if (buf[i] == '\n') lineCount++;
out.write(buf[i]);
i++;
}
}
}
public static void main(String[] argv) throws IOException {
if (argv.length != 2) {
String classname = new Error().getStackTrace()[0].getClassName();
System.err.println(
"Usage: " + classname + " <source-file> <destination-file>");
System.exit(1);
}
InputStream in = new FileInputStream(new File(argv[0]));
byte[] buf = new byte[in.available() + 1];
in.read(buf, 0, buf.length-1);
in.close();
OutputStream out =
new BufferedOutputStream(
new FileOutputStream(
new File(argv[1])));
try {
writeString(out,"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
writeString(out,"% DO NOT EDIT. Automatically generated file! %\n");
writeString(out,"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
writeString(out,"\n");
lineCount = 1;
process(buf, out);
} catch (RuntimeException ex) {
System.err.println ("\n **** error at line " + verbLine);
throw ex;
}
out.close();
}
}