This is part of a java program I wrote. As an option it is possible to highlight not only the language, but also the comments that are used by javadoc to create html api descriptions. Those comments can contain standard html tags which are highlighted. Also, as the first sentence is meant to be the title of the comment, it is highlighted differently.

Note that the colors may look strange on your screen, but they look very nice on mine.


import com.oroinc.text.regex.*;
import java.io.*;
import java.util.*;

/**
 * Reads the different files containing the rules. The rules 
 * are interpreted differently by looking at the file name.
 * To find the files the imgae path is checked for files with special names.
 * @author Claudio Fleiner <cfl@zurich.ibm.com>
 */
public class Rules {
        /** list of filesnames interpreted as facebiff files */
        static public String[] rcfiles={ ".faces","_faces","faces" };
        /** list of filesnames interpreted as faces files */
        static public String[] facebifffiles={ ".facealiases" };
        /** we use the oroinc perl pattern matcher */
        static private Perl5Compiler pc=new Perl5Compiler();
        /** the rules are initially stored in a vector */
        private Vector vrules=new Vector();
        /** when all rules have been read they are copied to an array */
        private Rule[] rules;

        /**
         * Constuctor with a list of path names formated the same way as the
         * CLASSPATH.
         * @param path list of directories separated by the path separater
         *        character
         */
        public Rules(String path) {
                StringTokenizer st=new StringTokenizer(path,File.pathSeparator);
                while(st.hasMoreTokens()) {
                        init(st.nextToken(),true);
                }
                rules=new Rule[vrules.size()];
                for(int i=0;i<rules.length;i++)
                        rules[i]=(Rule)vrules.elementAt(i);
                vrules=null;
        }

        /**
         * Search within a directory if there is a file with rules.
         * @param d directory to be searched
         * @param perl true if regular expressions are perl expressions, 
         *             but false if they are simple unix file regular
         *             expressions
         */
        private void init(String d,boolean perl) {
                File f=new File(d);
                if(f.isDirectory()) {
                        for(int i=0;i<rcfiles.length;i++)
                                init(d+File.separator+rcfiles[i],true);
                        for(int i=0;i<facebifffiles.length;i++)
                                init(d+File.separator+facebifffiles[i],false);
                } else if(f.canRead()) {
                        try {
                                FileReader fr=new FileReader(f);
                                BufferedReader bfr=new BufferedReader(fr);
                                String l;
                                while((l=bfr.readLine())!=null)
                                        addRule(l,perl);
                                bfr.close();
                                fr.close();
                        } catch(Exception e) { }
                }
        }

        /**
         * Add a rule to the list of rules
         * @param l rule to be added
         * @param perl set to true i fperl regular expression should be used,
         *             false if unix file regular expression are needed.
         */
        private void addRule(String l,boolean perl) {
                if(l==null || l.length()<2 || l.startsWith("#")) return;
                int b=l.indexOf(':');
                int s=l.lastIndexOf(' ');
                int t=l.lastIndexOf('\t');
                if(b<0 || (s<0 && t<0)) return;
                if(t>s) s=t;
                String h=l.substring(0,b);
                String i=l.substring(s+1);
                b++;
                while(l.charAt(b)==' ' || l.charAt(b)=='\t') b++;
                while(l.charAt(s)==' ' || l.charAt(s)=='\t') s--;
                String p=l.substring(b,s+1);
                Rule rule=new Rule();
                if(!perl) {
                        p=toPerl(p);
                        h=toPerl(h);
                }
                try { 
                        rule.header=(Perl5Pattern)pc.compile(h,Perl5Compiler.CASE_INSENSITIVE_MASK|Perl5Compiler.MULTILINE_MASK);
                } catch(MalformedPatternException e) {
                        System.err.println("Error compiling pattern "+h);
                        return;
                }
                try { 
                        rule.value=(Perl5Pattern)pc.compile(p,Perl5Compiler.CASE_INSENSITIVE_MASK|Perl5Compiler.MULTILINE_MASK);
                } catch(MalformedPatternException e) {
                        System.err.println("Error compiling pattern "+p);
                        return;
                }
                rule.image=i;
                vrules.addElement(rule);
        }

        /**
         * Convert a standard unix file regular expression to perl syntax.
         * i.e. replace '*' with ".*"
         *              '?' with '.'
         * and add a bunch of '\'
         */
        static private String toPerl(String r) {
                StringBuffer b=new StringBuffer();
                for(int i=0;i<r.length();i++) {
                        switch(r.charAt(i)) {
                        case '\\': if(i+1<r.length()) b.append('\\').append(r.charAt(++i));
                                   break;
                        case '.':  b.append("\\.");break;
                        case '?':  b.append('.');break;
                        case '*':  b.append(".*");break;
                        case '(':
                        case ')':
                        case '{':
                        case '}':
                        case '+':  b.append('\\'); // break missing on purpose
                        default:   b.append(r.charAt(i));
                        }
                }
                return b.toString();
        }

}