C#/.NET


C#/C++ のソースを HTML に変換する ツール CSharpToHTML


CtoHTML.cs

namespace CtoHTML
{
   /// <summary>CtoHTML</summary>
   class CtoHTML
   {
       #region Inner Class

       /// <summary>ToHTML</summary>
       class ToHTML
       {
           #region Implementers

           public static string filter(string text, bool preMode)
           {
               text            = TABtoSpace(text);
               text            = TrimEnd(text);

               System.Collections.ArrayList tokens = TokenBuilder.toTokens(text);

               string newText  = string.Empty;

               foreach (TokenBuilder.Token token in tokens)
               {
                   for (int index = 0; index <= token.text.Length; index++)
                   {
                       State oldState  = state;
                       state           = state.getState(token, index);
                       if (state.isChange && !oldState.GetType().Equals(state.GetType()))
                       {
                           newText += oldState.closeText();
                           newText += state   .openText ();
                       }
                       newText += toHTML(token.text, index, preMode);
                   }
               }
               if (state.lineEnd())
               {
                   State oldState  = state;
                   state           = state.getState();
                   if (state.isChange && !oldState.GetType().Equals(state.GetType()))
                   {
                       newText += oldState.closeText();
                       newText += state   .openText ();
                   }
               }
               newText += "<br>";
               return newText;
           }

           public static string end()
           {
               string text = state.closeText();
               state       = new NormalState();
               return text;
           }

           #endregion // Implementers

           #region Private

           private static string TABtoSpace(string text)
           {
               string newText = string.Empty;
               int column = 0;
               for (int index = 0; index < text.Length; index++)
               {
                   if (text[index] == '\t')
                   {
                       do
                       {
                           newText += ' ';
                           column++;
                       }
                       while ((column % (int)tab) != 0);
                   }
                   else
                   {
                       newText += text[index];
                       column++;
                   }
               }
               return newText;
           }

           private static string TrimEnd(string text)
           {
               char[] trimChars = new char[] {' '};
               return text.TrimEnd(trimChars);
           }

           private static string toHTML(string text, int index, bool preMode)
           {
               string newText = string.Empty;
               if (index < text.Length)
               {
                   switch (text[index])
                   {
                       case ' ' :
                           if (!preMode && index > 0 && text[index - 1] == ' ')
                               newText  = "&nbsp;";
                           else
                               newText  = " ";
                           break;
                       case '&' : newText  = "&amp;"    ; break;
                       case '<' : newText  = "&lt;"     ; break;
                       case '>' : newText  = "&gt;"     ; break;
                       case '\"': newText  = "&quot;"   ; break;
                       default  : newText += text[index]; break;
                   }
               }
               return newText;
           }

           private static State state = new NormalState();

           #endregion // Private
       }

       /// <summary>TokenBuilder</summary>
       class TokenBuilder
       {
           #region Inner Class

           /// <summary>Token</summary>
           public class Token
           {
               #region Enum

               public enum Kind
               {
                   WHITESPACE,
                   MARK      ,
                   SPECIAL   ,
                   OTHER
               }

               #endregion // Enum

               #region Constructors

               public Token()
               {}

               public Token(string text, Kind kind)
               {
                   text_ = text;
                   kind_ = kind;
               }

               #endregion // Constructors

               #region Implementers

               public virtual Token clone()
               {
                   return new Token(text, kind);
               }

               #endregion // Implementers

               #region Properties

               public string text
               {
                   get { return text_; }
                   set { text_ = value; }
               }
               public Kind kind
               {
                   get { return kind_; }
                   set { kind_ = value; }
               }

               #endregion // Properties

               #region Private

               private string  text_ = string.Empty;
               private Kind    kind_ = Kind.WHITESPACE;

               #endregion // Private
           }

           #endregion // Inner Class

           #region Constructors

           static TokenBuilder()
           {
               initializeHashTables();
           }

           #endregion // Constructors

           #region Implementers

           public static System.Collections.ArrayList toTokens(string text)
           {
               System.Collections.ArrayList tokens = new System.Collections.ArrayList();

               Token           current = new Token();

               for (int index = 0; index < text.Length; index++)
               {
                   object o = characterTable_[text[index]];
                   Token.Kind kind = (o == null) ? Token.Kind.OTHER : (Token.Kind)o;

                   if (kind == current.kind)
                   {
                       current.text += text[index];
                   }
                   else
                   {
                       if (current.text.Length > 0)
                       {
                           tokens.Add(current.clone());
                           current.text = string.Empty;
                       }
                       current.kind  = kind;
                       current.text += text[index];
                   }
               }
               if (current.text.Length > 0)
                   tokens.Add(current.clone());
               return tokens;
           }

           #endregion // Implementers

           #region Private

           private static char[] whiteSpaceCharacters_ = new char[] {' ', '\t', '\v', '\f', '\r', '\n'};
           private static char[] markCharacters_       = new char[] {'<', '>', '=', '+', '-', '*', '/', '%', '&', '|', '^', '!', '~', '.', '[', ']', '(', ')', '?', ':', '{', '}', ';'};
           private static char[] specialCharacters_    = new char[] {'\\', '\"', '\'', '\0', '\a', '\b'};

           private static System.Collections.Hashtable characterTable_ = new System.Collections.Hashtable();

           private static void initializeHashTables()
           {
               foreach (char c in whiteSpaceCharacters_)
                   characterTable_.Add(c, Token.Kind.WHITESPACE);
               foreach (char c in markCharacters_      )
                   characterTable_.Add(c, Token.Kind.MARK      );
               foreach (char c in specialCharacters_   )
                   characterTable_.Add(c, Token.Kind.SPECIAL   );
           }

           #endregion // Private
       }

       /// <summary>Keyword</summary>
       public class Keyword
       {
           #region Constants

           public const string comment1Start_  = "/*";
           public const string comment1End_    = "*/";
           public const string comment2Start_  = "//";

           #endregion // Constants

           #region Implementers

           public static void initialize()
           {
               initializeKeywordText();

               foreach (string s in csharpKeywordText_   )
                   csharpKeywordTextTable_   .Add(s, 0);
               foreach (string s in cplusplusKeywordText_)
                   cplusplusKeywordTextTable_.Add(s, 1);
           }

           public static bool isKeyword(string text)
           {
               return (keywordTextTable_[text] != null);
           }

           public static void initializeKeywordText()
           {
               System.Collections.ArrayList    textList        = new System.Collections.ArrayList();

               System.IO.TextReader            reader          = textReaderFromFile(csharpKeywordFileName);
               while (reader.Peek() > -1)
               {
                   string keyword = reader.ReadLine();
                   if (keyword.Length > 0)
                       textList.Add(keyword);
               }
               reader.Close();

               csharpKeywordText_      = new string[textList.Count];
               for (int i = 0; i < textList.Count; i++)
                   csharpKeywordText_[i] = (string)textList[i];

               textList.Clear();

               reader                                          = textReaderFromFile(cplusplusKeywordFileName);
               while (reader.Peek() > -1)
               {
                   string keyword = reader.ReadLine();
                   if (keyword.Length > 0)
                       textList.Add(keyword);
               }
               reader.Close();

               cplusplusKeywordText_   = new string[textList.Count];
               for (int i = 0; i < textList.Count; i++)
                   cplusplusKeywordText_[i] = (string)textList[i];

               textList.Clear();
           }

           #endregion // Implementers

           #region Properties

           public static ModeKind Mode
           {
               get
               {
                   return mode_;
               }
               set
               {
                   if (value != mode_)
                   {
                       mode_ = value;
                       switch (mode_)
                       {
                           case ModeKind.CSharp   : keywordTextTable_  = csharpKeywordTextTable_   ; break;
                           case ModeKind.CPlusPlus: keywordTextTable_  = cplusplusKeywordTextTable_; break;
                       }
                   }
               }
           }

           public static string keywordFileName
           {
               get
               {
                   switch (Mode)
                   {
                       case ModeKind.CSharp   : return csharpKeywordFileName   ;
                       case ModeKind.CPlusPlus: return cplusplusKeywordFileName;
                   }
                   return csharpKeywordFileName;
               }
           }

           #endregion // Properties

           #region Private

           private static ModeKind mode_ = ModeKind.CSharp;

           private const string csharpKeywordFileName    = @".\csharpkeyword.txt"   ;
           private const string cplusplusKeywordFileName = @".\cpluspluskeyword.txt";

           private static string[] csharpKeywordText_   ;
           private static string[] cplusplusKeywordText_;

           private static System.Collections.Hashtable csharpKeywordTextTable_     = new System.Collections.Hashtable();
           private static System.Collections.Hashtable cplusplusKeywordTextTable_  = new System.Collections.Hashtable();
           private static System.Collections.Hashtable keywordTextTable_           = csharpKeywordTextTable_;

           #endregion // Private
       }

       /// <summary>State</summary>
       abstract class State
       {
           #region Virtual

           public virtual string openText()
           {
               return string.Empty;
           }
           public virtual string closeText()
           {
               return string.Empty;
           }
           public virtual bool lineEnd()
           {
               return false;
           }

           public virtual State getState(TokenBuilder.Token token, int index)
           {
               if      (isSingleQuotation(token, index)) return new SingleQuotationState(token, index);
               if      (isDoubleQuotation(token, index)) return new DoubleQuotationState(token, index);
               else if (isComment1       (token, index)) return new Comment1State       ();
               else if (isComment2       (token, index)) return new Comment2State       ();
               else if (isKeyword        (token, index)) return new KeywordState        (token);
               else if (isMark           (token, index)) return new MarkState           ();
                                                         return new NormalState         ();
           }

           public virtual State getState()
           {
               return this;
           }

           #endregion // Virtual

           #region Properties

           public bool isChange
           {
               get
               {
                   bool isChangeFlag   = isChange_;
                   isChange_           = false;
                   return isChangeFlag;
               }
           }

           #endregion // Properties

           #region Protected

           private static bool isEscapeCharacter(TokenBuilder.Token token, int index)
           {
               return ((index >  0 && token.text[index - 1] == '\\') &&   // 一つ前が \ で且つ
                       (index <  2 || token.text[index - 2] != '\\'));    // 二つ前が \ でない
           }

           protected static bool isSingleQuotation(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
                       (index < token.text.Length && token.text[index] == '\'') &&
                       !isEscapeCharacter(token, index));
           }

           protected static bool isSingleQuotationEnd(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
                       (index > 0 && token.text[index - 1] == '\'') &&
                       !isEscapeCharacter(token, index - 1));
           }

           protected static bool isDoubleQuotation(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
                       (index < token.text.Length && token.text[index] == '\"') &&
                       !isEscapeCharacter(token, index));
           }

           protected static bool isDoubleQuotationEnd(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
                       (index > 0 && token.text[index - 1] == '\"') &&
                       !isEscapeCharacter(token, index - 1));
           }

           protected static bool isComment1(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.MARK &&
                       index < token.text.Length &&
                       string.Compare(token.text, index, Keyword.comment1Start_, 0, Keyword.comment1Start_.Length) == 0);
           }

           protected static bool isComment1End(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.MARK &&
                       index > 1 &&
                       string.Compare(token.text, index - Keyword.comment1End_.Length, Keyword.comment1End_, 0, Keyword.comment1End_.Length) == 0);
           }

           protected static bool isComment2(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.MARK &&
                       index < token.text.Length &&
                       string.Compare(token.text, index, Keyword.comment2Start_, 0, Keyword.comment2Start_.Length) == 0);
           }

           protected static bool isKeyword(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.OTHER &&
                       Keyword.isKeyword(token.text));
           }

           protected static bool isMark(TokenBuilder.Token token, int index)
           {
               return (token.kind == TokenBuilder.Token.Kind.MARK);
           }

           #endregion // Protected

           #region Private

           private bool isChange_ = true;

           #endregion // Private
       }

       /// <summary>NormalState</summary>
       class NormalState : State
       {}

       /// <summary>QuotationState</summary>
       abstract class QuotationState : State
       {
           #region Constructors

           protected QuotationState(TokenBuilder.Token token, int index)
           {
               token_ = token;
               index_ = index;
           }

           #endregion // Constructors

           #region Protected

           protected bool isSame(TokenBuilder.Token token, int index)
           {
               return (token == token_ && (index - 1) == index_);
           }

           #endregion // Protected

           #region Private

           private readonly TokenBuilder.Token token_;
           private readonly int                index_;

           #endregion // Private
       }

       /// <summary>SingleQuotationState</summary>
       class SingleQuotationState : QuotationState
       {
           #region Constructors

           public SingleQuotationState(TokenBuilder.Token token, int index) : base(token, index)
           {}

           #endregion // Constructors

           #region Override

           public override State getState(TokenBuilder.Token token, int index)
           {
               if (!isSame(token, index) && isSingleQuotationEnd(token, index))
                   return base.getState(token, index);
               return this;
           }

           public override string openText()
           {
               return singleQuotationTagOpen;
           }

           public override string closeText()
           {
               return singleQuotationTagClose;
           }

           #endregion // Override
       }

       /// <summary>DoubleQuotationState</summary>
       class DoubleQuotationState : QuotationState
       {
           #region Constructors

           public DoubleQuotationState(TokenBuilder.Token token, int index) : base(token, index)
           {}

           #endregion // Constructors

           #region Override

           public override State getState(TokenBuilder.Token token, int index)
           {
               if (!isSame(token, index) && isDoubleQuotationEnd(token, index))
                   return base.getState(token, index);
               return this;
           }

           public override string openText()
           {
               return doubleQuotationTagOpen;
           }

           public override string closeText()
           {
               return doubleQuotationTagClose;
           }

           #endregion // Override
       }

       /// <summary>CommentState</summary>
       abstract class CommentState : State
       {
           #region Override

           public override string openText()
           {
               return commentTagOpen;
           }

           public override string closeText()
           {
               return commentTagClose;
           }

           #endregion // Override
       }

       /// <summary>Comment1State</summary>
       class Comment1State : CommentState
       {
           #region Override

           public override State getState(TokenBuilder.Token token, int index)
           {
               if (isComment1End(token, index))
                   return base.getState(token, index);
               return this;
           }

           #endregion // Override
       }

       /// <summary>Comment2State</summary>
       class Comment2State : CommentState
       {
           #region Override

           public override bool lineEnd()
           {
               isEnd_ = true;
               return true;
           }

           public override State getState(TokenBuilder.Token token, int index)
           {
               return this;
           }

           public override State getState()
           {
               if (isEnd_)
               {
                   return new NormalState();
               }
               return this;
           }

           #endregion // Override

           #region Private

           private bool isEnd_ = false;

           #endregion // Private
       }

       /// <summary>KeywordState</summary>
       class KeywordState : State
       {
           #region Constructors

           public KeywordState(TokenBuilder.Token token)
           {
               token_ = token;
           }

           #endregion // Constructors

           #region Override

           public override State getState(TokenBuilder.Token token, int index)
           {
               if (token != token_ || index >= token.text.Length)
                   return base.getState(token, index);
               return this;
           }

           public override string openText()
           {
               return keywordTagOpen;
           }

           public override string closeText()
           {
               return keywordTagClose;
           }

           #endregion // Override

           #region Private

           private readonly TokenBuilder.Token token_;

           #endregion // Private
       }

       /// <summary>MarkState</summary>
       class MarkState : State
       {
           #region Override

           public override State getState(TokenBuilder.Token token, int index)
           {
               return base.getState(token, index);
           }

           public override string openText()
           {
               return markTagOpen;
           }

           public override string closeText()
           {
               return markTagClose;
           }

           #endregion // Override
       }

       /// <summary>Registry</summary>
       class Registry
       {
           #region Private

           private const string headerTextKeyName              = "Header Text";
           private const string footerTextKeyName              = "Footer Text";
           private const string singleQuotationTagOpenKeyName  = "Single Quotation Tag Open";
           private const string singleQuotationTagCloseKeyName = "Single Quotation Tag Close";
           private const string doubleQuotationTagOpenKeyName  = "Double Quotation Tag Open";
           private const string doubleQuotationTagCloseKeyName = "Double Quotation Tag Close";
           private const string commentTagOpenKeyName          = "Comment Tag Open";
           private const string commentTagCloseKeyName         = "Comment Tag Close";
           private const string keywordTagOpenKeyName          = "Keyword Tag Open";
           private const string keywordTagCloseKeyName         = "Keyword Tag Close";
           private const string markTagOpenKeyName             = "Mark Tag Open";
           private const string markTagCloseKeyName            = "Mark Tag Close";
           private const string encodingKeyName                = "Encoding";
           private const string tabKeyName                     = "TAB";
           private const string preModeKeyName                 = "Pre Mode";
           private const string modeKeyName                    = "Mode";
           private const string browserModeKeyName             = "Browser Mode";
           private const string browserKeyName                 = "Browser";

           #endregion // Private

           #region Implementers

           public static void read(Microsoft.Win32.RegistryKey key)
           {
               string[] texts  = (string[])key.GetValue(headerTextKeyName);
               if (texts != null)
                   headerText_                 = texts;
               texts           = (string[])key.GetValue(footerTextKeyName);
               if (texts != null)
                   footerText_                 = texts;
               string text     = (string)key.GetValue(singleQuotationTagOpenKeyName);
               if (text != null)
                   singleQuotationTagOpen_     = text;
               text            = (string)key.GetValue(singleQuotationTagCloseKeyName);
               if (text != null)
                   singleQuotationTagClose     = text;
               text            = (string