Copyright © 2001 by Neal R. Wagner. All rights reserved.
The following Java program will color comments dark red, keywords blue (including "true", "false", and "null", which are technically constants, but are reserved like keywords), Strings dark green, and character constants dark yellow.
It also translates the '<' character into "<" so that the program will handle HTML commands correctly. (The '<' character is the only one that causes trouble. When one wants '<' to appear inside HTML, one actually has to write '<'.) So this part of the program has a flaw. If the program encounters "<", it should translate this into "&lt;", but I did that by hand in the program below. (Thus this program does not quite correctly translate itself.)
Another odd point: when I wrote "&lt;" above, I wanted it to appear correctly in an HTML document, so I actually had to write "&amp;lt;". In order to write the quoted string I just wrote, I actually had to write "&amp;amp;lt;" for it, and in order to write this string . . . . In spite of all this, if you just select and copy from your browser, it will copy a correct Java program.
// Keywords.java: format a Java program for html
import java.io.*;
class Keywords {
private String[] keywords = {"abstract", "boolean", "byte", "case",
"catch", "char", "class", "continue", "default", "do", "double",
"else", "extends", "final", "finally", "float", "for", "if",
"implements", "import", "instanceof", "int", "interface", "long",
"native", "new", "package", "private", "protected", "public",
"return", "short", "static", "super", "switch", "synchronized",
"this", "throw", "throws", "transient", "try", "void", "volatile",
"while",
"false", "true", "null" // technically, constants, not keywords
};
private Reader in; // internal file name for input stream
private boolean fileOpen = false; // is the file open yet?
private String fileName; // name of input file, if present
// Keywords: constructor, input parameter: input file name or null
public Keywords(String f) {
fileName = f;
}
// getNextChar: fetches next char. Also opens input file
private char getNextChar() {
char ch = ' '; // = ' ' to keep compiler happy
if (!fileOpen) {
fileOpen = true;
if (fileName == null)
in = new InputStreamReader(System.in);
else {
try {
in = new FileReader(fileName);
} catch (IOException e) {
System.out.println("Exception opening " + fileName);
}
}
}
try {
ch = (char)in.read();
} catch (IOException e) {
System.out.println("Exception reading character");
}
return ch;
}
// buildDisplay: fetch each character and do the translation
public void buildDisplay() {
String word;
System.out.println("<html><pre>");
char ch = getNextChar();
char ch2 = ' '; // = ' ' to keep compiler happy
while (ch != 65535) { // EOF
// check for comment
if (ch == '/') {
ch = getNextChar();
if (ch == '/') { // first process one-line comments
System.out.print("<font color=\"#BB0000\">//"); // dark red
while ((ch = getNextChar()) != '\n') {
if (ch == '<') System.out.print("<");
else System.out.print(ch);
}
System.out.print("</font>");
}
else if (ch == '*') { // next process multi-line comment
System.out.print("<font color=\"#BB0000\">/*"); // dark red
ch = getNextChar();
ch2 = getNextChar();
while (true) {
if (ch == '*' && ch2 == '/') { // end of multi-line comm
System.out.print("*/</font>");
ch = getNextChar();
break;
}
else {
if (ch == '<') System.out.print("<");
else System.out.print(ch);
ch = ch2;
ch2 = getNextChar();
}
} // while
}
else { // not a comment, just a /
System.out.print("/");
if (ch == '<') System.out.print("<");
else System.out.print(ch);
ch = getNextChar();
}
} // end of comment handler
// check for quoted string (between "")
else if (ch == '"') {
System.out.print("<font color=\"#006600\">\""); // dark green
while (true) {
ch = getNextChar();
// need the following to handle \" in a String
if (ch == '\\') {
ch = getNextChar();
System.out.print("\\");
if (ch == '<') System.out.print("<");
else System.out.print(ch);
}
else if (ch == '"') {
System.out.print("\"</font>");
ch = getNextChar();
break;
}
else {
if (ch == '<') System.out.print("<");
else System.out.print(ch);
}
} // while
} // end of quoted String handler
// check for character constant (between '')
else if (ch == '\'') {
System.out.print("<font color=\"#B0B000\">\'"); // dark yellow
while (true) {
ch = getNextChar();
// need the following to handle \' in a char constant
if (ch == '\\') {
ch = getNextChar();
System.out.print("\\");
if (ch == '<') System.out.print("<");
else System.out.print(ch);
}
else if (ch == '\'') { // end of character constant
System.out.print("\'</font>");
ch = getNextChar();
break;
}
else {
if (ch == '<') System.out.print("<");
else System.out.print(ch);
}
} // while
} // end of character constant handler
// check for keyword
else if (Character.isLetter(ch)) {
word = "" + ch;
while (Character.isLetter(ch = getNextChar()))
word += ch;
if (Character.isDigit(ch) || ch == '_') {
System.out.print(word); // just bail out
while (Character.isLetterOrDigit(ch) || ch == '_') {
System.out.print(ch);
ch = getNextChar();
}
}
else { // check word if keyword
if (lookUp(word) != -1) {
System.out.print("<font color=\"#0000BB\">" // blue
+ word + "</font>");
}
else
System.out.print(word);
}
} // end of keyword handler
if (ch == '<') System.out.print("<");
else System.out.print(ch);
ch = getNextChar();
}
System.out.println("</pre></html>");
}
// lookUp: loop up the next word in the array keywords
public int lookUp(String s) {
for (int j = 0; j < keywords.length; j++)
if (s.equals(keywords[j])) return j;
return -1;
}
// main: doesn't do much; just feeds in input file name
public static void main(String[] args) {
Keywords key;
// pass an input file name if present on command line
if (args.length > 0)
key = new Keywords(args[0]);
else
key = new Keywords(null);
key.buildDisplay();
}
}