21.5 (Syntax highlighting)
Write a program that converts a Java file into an HTML file.
In the HTML file, the keywords, comments, and literals are displayed
in bold navy, green, and blue, respectively. Use the command line to
pass a Java file and an HTML file. For example, the following command
java Exercise21_05 Welcome.java Welcome.html
converts Welcome.java into Welcome.html. Figure 21.8a shows a Java file.
The corresponding HTML file is shown in Figure 21.8b.
Write a program that converts a Java file into an HTML file.
In the HTML file, the keywords, comments, and literals are displayed
in bold navy, green, and blue, respectively. Use the command line to
pass a Java file and an HTML file. For example, the following command
java Exercise21_05 Welcome.java Welcome.html
converts Welcome.java into Welcome.html. Figure 21.8a shows a Java file.
The corresponding HTML file is shown in Figure 21.8b.
import java.io.*; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.*; public class Exercise_05 { public static void main(String[] args) throws Exception { String filename = "Loan.java"; File file = new File(filename); if (file.exists()) { System.out.println(file.getName() + " has been parsed to html " + parseToHTML(file)); } else { System.out.println("File " + filename + " does not exist"); } } private static boolean[] states = new boolean[4]; private static int BLOCK = 0; private static int LINE = 1; private static int STRING = 2; private static int CHAR = 3; public static int parseToHTML(File file) throws Exception { Scanner input = new Scanner(file); int count = 0; String word = ""; while (input.hasNext()) { word += input.nextLine() + "\n"; } int index; int prevIndex = 0; while ((index = getNextState(word, lastIndex)) != -1) { if (index > lastIndex) { word = parseSyntax(word, lastIndex, index); // for (int i = 0; i < states.length; i++) // states[i] = false; // index = getNextState(word, lastIndex); index = lastIndex; } if (states[BLOCK]) word = parseBlock(word, index); else if (states[LINE]) word = parseLine(word, index); else if (states[STRING]) word = parseString(word, index); else if (states[CHAR]) word = parseChar(word, index); prevIndex = lastIndex; } if (prevIndex < word.length()) { word = parseSyntax(word, prevIndex, word.length()); } word = getHeader() + word + getFooter(); // ByteBuffer parsedHTML = Charset.forName("UTF-8").encode(word); // Save to a html file try (FileOutputStream out = new FileOutputStream("test3.html")) { out.write(word.getBytes()); } catch (IOException ex) { } return count; } // Array of all Java keywords + true, false and null private static HashSet<String> keywords = new HashSet<>(Arrays.asList( "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "for", "final", "finally", "float", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", "true", "false", "null")); private static String parseSyntax(String s, int startIndex, int last) { String beforeSyntax = s.substring(0, startIndex); String syntax = s.substring(startIndex, last); syntax = parseSyntax(syntax, false); String[] splitSyntax = syntax.split("(\\|\\|\\|\\|\\|)|((?<=\\()|(?=\\)))"); syntax = ""; for (String split : splitSyntax) { System.out.println(split); if (keywords.contains(split)) { syntax += wrapWithSpanTag(split, "blue"); } else { syntax += split; } } String afterString = s.substring(last); lastIndex = beforeSyntax.length() + syntax.length(); return beforeSyntax + syntax + afterString; } private static int lastIndex; private static String parseString(String word, int index) { states[STRING] = false; String beforeString = word.substring(0, index); String unknownLiteral = word.substring(index); int escape = unknownLiteral.indexOf("\\", 1); // escape sequence (back slash) int dQuote = unknownLiteral.indexOf("\"", 1); // double quote // Does this string literal have any escape sequence? if (escape == -1 || escape > dQuote) { // If no, save string literal to the hash map, then return the string String strLiteral = unknownLiteral.substring(0, dQuote + 1); // + 1 to include double quote String afterLiteral = unknownLiteral.substring(dQuote + 1); strLiteral = parseToHTML(strLiteral, true); strLiteral = wrapWithSpanTag(strLiteral, "green"); lastIndex = beforeString.length() + strLiteral.length(); return beforeString + strLiteral + afterLiteral; } // Code reaches here is this string has an escape sequence // Find the next double quote that doesn't have an escape character Stack<Character> tokens = new Stack<>(); char[] charArray = unknownLiteral.toCharArray(); for (int i = 1; i < charArray.length; i++) { char ch = charArray[i]; if (ch == '\"' && tokens.isEmpty()) { String strLiteral = unknownLiteral.substring(0, i + 1); // +1 to include " strLiteral = parseToHTML(strLiteral, true); strLiteral = wrapWithSpanTag(strLiteral, "green"); lastIndex = beforeString.length() + strLiteral.length(); return beforeString + strLiteral + unknownLiteral.substring(i + 1); } if (!tokens.isEmpty()) tokens.pop(); else if (ch == '\\') { tokens.push(ch); } } return "ERROR FINDING END OF STRING"; } private static String parseSyntax(String s, boolean isStrLiteral) { s = s.replaceAll("&", "|||||&|||||"); s = s.replaceAll("<", "|||||<|||||"); s = s.replaceAll(">", "|||||>|||||"); s = s.replaceAll("\"", "|||||"|||||"); s = s.replaceAll(" ", "||||| |||||"); if (!isStrLiteral) { s = s.replaceAll("\n", "|||||<br>|||||"); s = s.replaceAll("\t", "||||| ||||| ||||| ||||| ||||| "); } return s; } private static String parseToHTML(String s, boolean isStrLiteral) { s = s.replaceAll("&", "&"); s = s.replaceAll("<", "<"); s = s.replaceAll(">", ">"); s = s.replaceAll("\"", """); s = s.replaceAll(" ", " "); if (!isStrLiteral) { s = s.replaceAll("\n", "<br>"); s = s.replaceAll("\t", " "); } return s; } private static String parseLine(String s, int index) { states[LINE] = false; String beforeLine = s.substring(0, index); String unknownLine = s.substring(index); int eof = unknownLine.indexOf("\n"); String line = unknownLine.substring(0, eof); line = parseToHTML(line, false); String afterLine = unknownLine.substring(eof + 1); // ignore \n line = wrapWithSpanTag(line, "orange") + "<br>"; // append new line (<br>) lastIndex = beforeLine.length() + line.length(); return beforeLine + line + afterLine; } private static String parseChar(String word, int index) { states[CHAR] = false; String beforeChar = word.substring(0, index); String unknownLiteral = word.substring(index); String charLiteral; if (unknownLiteral.charAt(1) == '\\') // if there's an escape sequence charLiteral = unknownLiteral.substring(0, 4); else charLiteral = unknownLiteral.substring(0, 3); String afterChar = word.substring(index + charLiteral.length()); charLiteral = parseToHTML(charLiteral, true); charLiteral = wrapWithSpanTag(charLiteral, "green"); lastIndex = beforeChar.length() + charLiteral.length(); return beforeChar + charLiteral + afterChar; } private static String parseBlock(String s, int index) { states[BLOCK] = false; String beforeBlock = s.substring(0, index); int endIndex = s.indexOf("*/", index) + 2; // +2 for /* String block = s.substring(index, endIndex); String afterBlock = s.substring(endIndex); block = parseToHTML(block, false); block = wrapWithSpanTag(block, "orange"); lastIndex = beforeBlock.length() + block.length(); return beforeBlock + block + afterBlock; } private static String getHeader() { return "<!DOCTYPE html><html><head lang=\"en\"><meta charset=\"UTF-8\"><title></title></head><body>"; } private static String getFooter() { return "</body></html>"; } public static int getNextState(String s, int startIndex) { // block, line, string, char int[] indices = new int[4]; String[] startStateTokens = {"/*", "//", "\"", "\'"}; int lowest = -1; int key = 0; for (int i = 0; i < indices.length; i++) { indices[i] = s.indexOf(startStateTokens[i], startIndex); if (lowest == -1) { lowest = indices[i]; key = i; } else if (lowest > indices[i] && indices[i] >= 0) { lowest = indices[i]; key = i; } } // Set the current state if (key != -1) { states[key] = true; } return indices[key]; } private static String wrapWithSpanTag(String s, String color) { return "<span style=\"color:" + color + ";\">" + s + "</span>"; } }
No comments :
Post a Comment