阅读文章

代码着色--关于循环与分组

[日期:2008-04-24] 来源:  作者: [字体: ]

     本来这个功能应该算是编辑器的一个附属功能,本来有一个JS的代码着色器(syntaxhighlighter),现在版本是1.51,但是由于其功能始终是客户端的,有一些服务器操作比较麻烦,于是自己写了一个,当前只是实现了C#版本。
  在这里,我讲述一下该代码实现模式,这里主要讲讲循环和分组的机制
  
  主体:
  
  
  HighLightCode:为高亮代码的基类,并抽象,含有抽象方法
  通过方法实现实例
  
  
  public static HighLightCode CreateHighLightCode(CodeType regexcodetype)
   {
   HighLightCode code = null;
   if (regexcodetype == CodeType.CSharp)
   {
   code = new RegexCSharp();
   }
  
   return code;
   }
  
  RegexCSharp:实现HighLightCode方法。
  当前为C#实现了该方法,如果Java类实现该方法,则可以扩展出Java的着色代码.
  
  思路:
  如果我们直接使用正则表达式进行匹配,那么比较麻烦,会出现一些问题,如://string abc = "hello";那么"hello"会被分析为引号部分,而非注释部分。要解决该问题,我们先分析一下代码着色的原理和基础。
  特殊的符号包括单引号,双引号,单行注释,多行注释的判断,由于这些情况都是成对的出现,我们需要找出这4个情况前后匹配的数据进行分组处理。
  注意,单行注释由//开头,\r\n结尾
  如:string abc= "hello!";
  那么string abc=作为group1,"hello!"作为group2,;作为group3。那么在group1和group3我们需要的仅仅是对关键字进行匹配,在这里最简单的方法就是正则表达式进行匹配和着色。那么对于group2无非就是添加深红色而已。但是对于分组我们需要找到最先出现的符号位置,如:string abc = "hello // world!";此时的//应该作为字符串而非注释,所以它必须为group2中。
  
  分组方法:
  我们先讨论只有一个目标符号的情况。即:string abc= "hello!";
  我们首先将4个符号的出现的初始位置找到,进行排序,得到位置最小的符号,那么该组就是以该符号为基准。在这里,我使用了List进行排序。得到位置最小的符号组,那么它就是我们要寻找的目标符号,于是寻找他的结尾符号,则可以得到它具体的字符串。
  
  循环流程:
  由于程序不会只有一个目标符号,如:
  string a1= "hello!";
  string a2= "i love you!";
  //string "a3";
  上面实例则存在7个组
  group1=string a1=
  group2="hello!"
  group3=;
  group4=string a2=
  group5="i love you!"
  group6=;
  group7=//string "a3";
  
  这样的组会存在多个,于是我们从目标字符串的0位置开始到它的长度进行循环(for(int i=0;i<code.length;i++)),得到多个的目标组。
  
  
  该图展示了查找的判断逻辑,每找到一个组,则实例出RegexItem,放置到List<RegexItem>集合中。
  
  List<RegexItem> items = new List<RegexItem>();
   private int CreateItem(string code, int start)
   {
   List<RegexItem> regexs = new List<RegexItem>();
   RegexItem regx = null;
  
   int count = 0;
   int pos1 = code.IndexOf('"', start);
   if (pos1 > -1)
   {
   count++;
   regx = new RegexItem();
   regx.Postion = pos1;
   regx.RegexMode = Mode.DoubleQuotedString;
   regexs.Add(regx);
   }
   int pos2 = code.IndexOf(BeginSingleLineComments, start);
   if (pos2 > -1)
   {
   count++;
   regx = new RegexItem();
   regx.Postion = pos2;
   regx.RegexMode = Mode.SingleLineComments;
   regexs.Add(regx);
   }
   int pos3 = code.IndexOf(BeginMultiLineComments, start);
   if (pos3 > -1)
   {
   count++;
   regx = new RegexItem();
   regx.Postion = pos3;
   regx.RegexMode = Mode.MultiLineComments;
   regexs.Add(regx);
   }
   int pos4 = code.IndexOf("'", start);
   if (pos4 > -1)
   {
   count++;
   regx = new RegexItem();
   regx.Postion = pos4;
   regx.RegexMode = Mode.SingleQuotedString;
   regexs.Add(regx);
   }
   RegexItem minItem = null;
   if (count > 0)
   {
  
   if (regexs.Count > 1)
   {
   Comparison<RegexItem> comp = new Comparison<RegexItem>(SortItmes);
   regexs.Sort(comp);
   minItem = regexs[0];
   }
   else if (regexs.Count == 1)
   {
   minItem = regexs[0];
   }
   }
   else
   {
   minItem = new RegexItem();
   minItem.Postion = start;
   minItem.RegexMode = Mode.Default;
   }
   int end = 0;
  
  
   RegexItem itemFirst = new RegexItem();
   itemFirst.RegexMode = Mode.Default;
   itemFirst.Postion = start;
   if (minItem.RegexMode == Mode.DoubleQuotedString)
   {
   end = code.IndexOf('"', minItem.Postion + 1);
   itemFirst.Text = code.Substring(start, minItem.Postion - start);
   items.Add(itemFirst);
   minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
   items.Add(minItem);
   }
   else if (minItem.RegexMode == Mode.SingleLineComments)
   {
   end = code.IndexOf(EndSingleLineComments, minItem.Postion + 1);
   if (end == -1) { end = code.Length - 1; }//为最后一行
   else { end++; }//因为\r\n占两个字节
  
   itemFirst.Text = code.Substring(start, minItem.Postion - start);
   items.Add(itemFirst);
   minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
   items.Add(minItem);
   }
   else if (minItem.RegexMode == Mode.MultiLineComments)
   {
   end = code.IndexOf(EndMultiLineComments, minItem.Postion + 1);
   itemFirst.Text = code.Substring(start, minItem.Postion - start);
   items.Add(itemFirst);
   minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
   items.Add(minItem);
   }
   else if (minItem.RegexMode == Mode.SingleQuotedString)
   {
   end = code.IndexOf("'", minItem.Postion + 1);
   itemFirst.Text = code.Substring(start, minItem.Postion - start);
   items.Add(itemFirst);
   minItem.Text = code.Substring(minItem.Postion, end - minItem.Postion + 1);
   items.Add(minItem);
   }
   else
   {
   // end = code.IndexOf(start, minItem.Postion - start + 1);
   end = code.Length - 1;
   minItem.Text = code.Substring(start, code.Length - start);
   items.Add(minItem);
   }
  
   return end;
   }
  public string GetHighLightCode(string code)
   {
   int i = 0;
   //循环判断逻辑
   for (; i < code.Length; i++)
   {
   int start = CreateItem(code, i);
   i = start;
   }
  
   }
  
  当然,如果没有源码的朋友可以到http://www.cnblogs.com/KeithDan/archive/2008/04/23/1168279.HTML 去下载
  
    


阅读:
录入:blue1000

评论 】 【 推荐 】 【 打印
上一篇:介绍WS Federaion 二:把百度和谷歌和谐起来
下一篇:My97日期控件 My97 DatePicker 4.0 Prerelease 发布
相关文章      
本文评论
发表评论


点评: 字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款