Wednesday, March 09, 2005
Colorizer: For C#, Java, C, C++
This Colorizer is implemented in C#. The implementation of colorizer basically started of to be a good choice to demonstrate the use of regular expression (atleast the basic) and few useful syntax the C# provides, like inside the swtich statement, the handling of dictionary. You can use this colorizer to colorize the java, c, c++ or c# code. Before I end this entry let me tell one small thing [I used the same colorizer to colorize the source shown below :)]. Download
View Colorizer.csHide Colorizer.cs
// Author: Prasad.A
using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace CSharpUtils {
// Class that describes keywords and creates a dictionary
// lookup depending on the language selection.
class CKeyword {
// Dictionary to lookup the keyword.
private IDictionary keydict = null;
// Java language keywords
protected string[] jkeywords = {
"abstract", "default", "goto", "package", "synchronized",
"boolean", "do", "if", "private", "this",
"break", "double", "implements", "protected","throw",
"byte", "else", "import", "public", "throws",
"case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try",
"char", "final", "interface", "static", "void",
"class", "finally", "long", "strictfp", "volatile",
"const", "float", "native", "super", "while",
"continue", "for", "new", "switch"
};
// C# language keywords
protected string[] cskeywords = {
"abstract", "event", "new", "struct",
"as", "explicit", "null", "switch",
"base", "extern", "object", "this",
"bool", "false", "operator", "throw",
"break", "finally", "out", "true",
"byte", "fixed", "override", "try",
"case", "float", "params", "typeof",
"catch", "for", "private", "uint",
"char", "foreach", "protected","ulong",
"checked", "goto", "public", "unchecked",
"class", "if", "readonly", "unsafe",
"const", "implicit", "ref", "ushort",
"continue", "in", "return", "using",
"decimal", "int", "sbyte", "virtual",
"default", "interface","sealed", "volatile",
"delegate", "internal", "short", "void",
"do", "is", "sizeof", "while",
"double", "lock", "stackalloc",
"else", "long", "static",
"enum", "namespace","string"
};
// C language keywords
protected string[] ckeywords = {
"auto", "double", "int", "struct",
"break", "else", "long", "switch",
"case", "enum", "register", "typedef",
"char", "extern", "return", "union",
"const", "float", "short", "unsigned",
"continue", "for", "signed", "void",
"default", "goto", "sizeof", "volatile",
"do", "if", "static", "while"
};
// C++ language keywords
protected string[] cppkeywords = {
"asm", "auto", "bool", "break", "case",
"catch", "char", "class", "const", "continue",
"default", "delete", "do", "double", "else",
"enum", "explicit", "extern", "false", "float",
"for", "friend", "goto", "if", "inline",
"int", "long", "mutable", "namespace",
"new", "operator", "private", "protected", "public",
"register", "return", "short", "signed", "sizeof",
"static", "struct", "switch", "template", "this",
"throw", "true", "try", "typedef", "typeid",
"typename", "union", "unsigned", "using", "virtual",
"void", "volatile", "while"
};
// Default Language is C#
public CKeyword() { initKeyDict("c#"); }
// Set the user specified language
public CKeyword(string language) { initKeyDict(language); }
// Initialize the keyword lookup dictionary
public void initKeyDict(string language) {
string[] initKeywords = null;
if(language=="c#"||language==null) initKeywords = cskeywords;
else if(language=="java") initKeywords = jkeywords;
else if(language=="c") initKeywords = ckeywords;
else if(language=="c++") initKeywords = cppkeywords;
keydict = new Hashtable();
for(int i=0; i < initKeywords.Length; ++i) {
keydict[initKeywords[i]] = "";
}
}
// Check whether the given word is a keyword
protected bool isKeyword(String word) { return keydict.Contains(word); }
}
// Class that will do the coloring of input file
class Colorizer : CKeyword {
private bool inDocumentation = false; // Are we inside the documentation
private bool inComment = false; // Are we inside the comment
private string filename = null; // File under processing
private bool completeHtml = false; // Should the output be complete html
// Default constructor
public Colorizer() { }
// Constructor to set the language type and output type
public Colorizer(string language,bool completeHtml) : base(language) {
this.completeHtml = completeHtml;
}
// Actual function that will colorize the input file and dumps the
// output to output file (if null then standard output will be used)
public void colorize(string infile,string outfile) {
// Set the file name under process.
filename = infile;
StreamReader instream = new StreamReader(filename);
// Set the console output to file if outfile is specified
if(outfile != null) Console.SetOut(new StreamWriter(outfile));
// If output should be complete html put the headers
if(completeHtml) writeHtmlHeaders();
// Parse each line and the process it
for(string line; (line = instream.ReadLine()) != null; ) {
bool doParse = true;
while(doParse) {
IDictionary dictionary = parseLine(line);
dictionary["line"] = line;
line = processResult(dictionary);
if(line == null) doParse = false;
}
}
// If output is complete html put the footers
if(completeHtml) writeHtmlFooters();
// Close the output stream
if(outfile != null) Console.Out.Close();
}
// Write starting html tags
private void writeHtmlHeaders() {
Console.Write("<html><head><title>"+filename+"</title>");
Console.Write("<style type='text/css'>");
Console.Write(".body { font: 10pt Verdana, sans-serif; }");
Console.Write(".keyword { color: blue;} ");
Console.Write(".comment { color: green;} ");
Console.Write(".document { color: #777777;} ");
Console.Write(".string { color: brown;} ");
Console.Write("</style>");
Console.WriteLine("</head>");
Console.Write("<body><pre>");
}
// Write ending html tags
private void writeHtmlFooters() {
Console.Write("</pre></body></html>");
}
// Parse each line of input
private IDictionary parseLine(string line) {
// Core pattern that will break the line into token
string pattern = @"(/\*\*?)|(\*/)|(//)|(\w+)|([ \t\r\n]+)|("".*"")|([^*/\w\t\r\n ])|([/\*])";
// Get the token
Match match = Regex.Match(line,pattern);
// Set the result as dictionary
IDictionary dictionary = new Hashtable();
dictionary["index"] = match.Index;
dictionary["length"] = match.Length;
return dictionary;
}
// Process the match
private string processResult(IDictionary dictionary) {
int index = (int) dictionary["index"];
int length = (int) dictionary["length"];
string line = (string) dictionary["line"];
if(length==0) { Console.WriteLine(); return null; }
else {
return processToken(line.Substring(index,length),
line.Substring(index+length));
}
}
// Process the token
private string processToken(string token,string remenant) {
bool inline = true;
switch(token) {
case "/*":
inComment = true;
if(completeHtml) Console.Write("<span class='comment'>");
else Console.Write("<span style='{color:green;}'>");
Console.Write(convertToHtml(token));
break;
case "/**":
inDocumentation = true;
if(completeHtml) Console.Write("<span class='document'>");
else Console.Write("<span style='{color:#777777;}'>");
Console.Write(convertToHtml(token));
break;
case "*/":
Console.Write(token);
if(inComment || inDocumentation) Console.Write("</span>");
inComment = inDocumentation = false;
break;
case "//":
if(completeHtml) Console.Write("<span class='comment'>");
else Console.Write("<span style='{color:green;}'>");
Console.WriteLine(convertToHtml(token+remenant));
Console.Write("</span>");
remenant=null;
break;
default:
if(inComment || inDocumentation) Console.Write(token);
else {
if(base.isKeyword(token)) {
if(completeHtml)
Console.Write("<span class='keyword'>");
else Console.Write("<span style='{color:blue;}'>");
Console.Write(convertToHtml(token));
Console.Write("</span>");
}
else if(token.StartsWith("\"") && token.EndsWith("\"")) {
if(completeHtml)
Console.Write("<span class='string'>");
else Console.Write("<span style='{color:brown;}'>");
Console.Write(convertToHtml(token));
Console.Write("</span>");
}
else
Console.Write(convertToHtml(token));
}
break;
}
return remenant;
}
// Format the text to put as html
private StringBuilder convertToHtml(string text) {
StringBuilder sb = new StringBuilder(text);
sb = sb.Replace("<","<");
sb = sb.Replace(">",">");
return sb;
}
// Display the version and exit
private static void printVersion() {
Console.WriteLine("Colorizer, Version 1.0, Author: Prasad.A");
System.Environment.Exit(0);
}
// Display the help and exit
private static void printHelp() {
Console.WriteLine("Usage: ");
Console.WriteLine("mono Colorizer.exe [-l language] [-o outputfile] [--html] [--help,-h] [--version,-v] inputfile");
Console.WriteLine("-l: Language selection, one of them [c# java c c++]");
Console.WriteLine("-o: Output file name, (default to standard output)");
Console.WriteLine("--html: For complete html output.");
Console.WriteLine("-h, --help: This help.");
Console.WriteLine("-v, --version: Version and Author information.");
System.Environment.Exit(0);
}
private static String getLanguage(String language) {
String specifiedLang = language.ToLower();
if( String.Compare("c#",specifiedLang) == 0 ||
String.Compare("java",specifiedLang) == 0 ||
String.Compare("c",specifiedLang) == 0 ||
String.Compare("c++",specifiedLang) == 0 ) {
return specifiedLang;
} else {
Console.WriteLine("Unsupported language: "+language);
Console.WriteLine("Supported language: c#, java, c, c++");
System.Environment.Exit(1);
return null;
}
}
// Main function to run the Colorizer.
public static void Main(string[] args) {
string language = null;
string inputfile = null;
string outputfile = null;
bool completeHtml = false;
// Handle command line arguments
if(args.Length > 0) {
for(int i = 0; i < args.Length; ++i) {
switch(args[i]) {
case "-o":
if(i < args.Length-1) outputfile = args[++i];
else printHelp();
break;
case "-l":
if(i < args.Length-1) language = getLanguage(args[++i]);
else printHelp();
break;
case "--help": printHelp(); break;
case "-h": printHelp(); break;
case "--version": printVersion(); break;
case "-v": printVersion(); break;
case "--html": completeHtml = true; break;
default: inputfile = args[i]; break;
}
}
}
// If input file is not specified, print help and exit
if(inputfile == null) printHelp();
// Start the colorizer after initalization
Colorizer colorizer = new Colorizer(language,completeHtml);
colorizer.colorize(inputfile,outputfile);
}
}
}
# posted by Prasad.A : 5:39 AM