昨天有人问怎么用RichTextBox做语法高亮
这就需要用到语法分析
还有很多论坛里也支持语法高亮的功能、代码折叠的功能
这也算是一个常用的功能
所以就随手搭建一个语法分析的框架
思路是利用正则表达式逐步取得各种语法构成部分这里欢迎大家测试、找BUG、完善正则表达式
谢谢参与
初步代码如下:
/// <summary>
/// 语法分析引擎基类
/// </summary>
class SyntaxEngine
{
    /// <summary>
    /// 语法项
    /// </summary>
    public class SyntaxItem
    {
        #region 私有字段
        private string FPattern; // 正则表达式
        private RegexOptions FOptions; // 正则表达式附加选项
        private string FName; // 语法名称
        private int FIndex; // 序号
        #endregion 私有字段        #region 公有属性
        public string Pattern { get { return FPattern; } } // 正则表达式
        public RegexOptions Options { get { return FOptions; } } // 正则表达式附加选项
        public string Name { get { return FName; } } // 名称
        public int Index { get { return FIndex; } } // 序号
        #endregion 公有属性        public SyntaxItem(string APattern, RegexOptions AOptions, 
            string AName, int AIndex)
        {
            FPattern = APattern;
            FOptions = AOptions;
            FName = AName;
            FIndex = AIndex;
        }
    }
    /// <summary>
    /// 语法分析返回项
    /// </summary>
    public class AnalyzeReslut 
    {
        #region 私有字段
        private SyntaxItem FItem; // 所属语法项
        private string FBlock; // 文字块
        #endregion 私有字段        #region 公有属性
        public SyntaxItem Item { get { return FItem; } }
        public string Block { get { return FBlock; } }
        #endregion 公有属性        public AnalyzeReslut(SyntaxItem AItem, string ABlock)
        {
            FItem = AItem;
            FBlock = ABlock;
        }
    }    private List<SyntaxItem> FSyntaxItems = new List<SyntaxItem>();
    private List<AnalyzeReslut> FAnalyzeResluts = new List<AnalyzeReslut>();    public List<SyntaxItem> SyntaxItems { get { return FSyntaxItems; } }
    public List<AnalyzeReslut> AnalyzeResluts { get { return FAnalyzeResluts; } }    /// <summary>
    /// 进行语法分析
    /// </summary>
    /// <param name="ACode">所分析的代码</param>
    /// <returns>返回分析是否成功</returns>
    public virtual bool Analyze(string ACode)
    {
        if (FSyntaxItems.Count <= 0) return false;
        if (ACode == null) return false;
        AnalyzeResluts.Clear();
        string vCode = ACode;
        bool vFind = true;
        while (vFind && (vCode.Length > 0))
        {
            vFind = false;
            foreach (SyntaxItem vSyntaxItem in FSyntaxItems)
            {
                if (Regex.IsMatch(vCode, vSyntaxItem.Pattern, vSyntaxItem.Options))
                {
                    AnalyzeResluts.Add(new AnalyzeReslut(vSyntaxItem, 
                        Regex.Match(vCode, vSyntaxItem.Pattern, 
                        vSyntaxItem.Options).Value));
                    vCode = Regex.Replace(vCode, vSyntaxItem.Pattern, "",
                        vSyntaxItem.Options);
                    vFind = true;
                    break;
                }
            }
        }
        return true;
    }
}class CSharpEngine : SyntaxEngine
{                                                
    public CSharpEngine()
    {
        SyntaxItems.Add(new SyntaxItem(@"^\s+", RegexOptions.None,
            "空白", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^\/\/[^\n]*[\n]?", RegexOptions.None,
            "单行注释", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^\/\*[^\*]*\*\/", RegexOptions.None,
            "多行注释", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^#\s*(define|elif|else|endif|endregion|" + 
            @"error|if|line|pragma|region|undef|using|warning)\s*", RegexOptions.None,
            "指令", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^(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|int|return|using|decimal|in|sbyte|virtual|default|interface|" +
            @"sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|" +
            @"double|lock|stackalloc|else|long|static|enum|namespace|string)\s*",
            RegexOptions.None, "关键字", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^(get|partial|set|value|where|yield)\s*",
            RegexOptions.None, "上下文关键字", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(
            @"^[\~\!\@\#\$\%\^\&\*\(\)_\+\-\=\{\}\[\]\\\|\;\\:\<\>\?\,\.\/]+",
            RegexOptions.None, "标点符号", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^\d+", RegexOptions.None, 
            "整数", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^0x[\da-f]+", RegexOptions.IgnoreCase, 
            "十六进制数", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^(\@)?\""[^\""]*\""", RegexOptions.None,
            "字符串", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^\'[^\']*\'", RegexOptions.None,
            "字符", SyntaxItems.Count));
        SyntaxItems.Add(new SyntaxItem(@"^\w*", RegexOptions.None,
            "标识符", SyntaxItems.Count));
    } 
}

解决方案 »

  1.   

    -----------------------调试代码如下:-----------------------
    private void button1_Click(object sender, EventArgs ce)
    {
        CSharpEngine vCSharpEngine = new CSharpEngine();
        vCSharpEngine.Analyze(textBox1.Text);    textBox2.Clear();
        foreach (CSharpEngine.AnalyzeReslut
            vAnalyzeReslut in vCSharpEngine.AnalyzeResluts)
        {
            textBox2.AppendText(vAnalyzeReslut.Item.Name + ":" +
                vAnalyzeReslut.Block);
        }
    }
    -----------------------输入范例:-----------------------
    // 排列组合
    public void CombinationCollocate(List<string> AStrings, string ANumbers, string APath, int ALen)
    {
        if (APath.Length >= ALen)
        {
            AStrings.Add(APath);
            return;
        }
        for (int i = 0; i < ANumbers.Length; i++)
        {
            string vNumbers = ANumbers.Remove(i, 1);
            CombinationCollocate(AStrings, vNumbers, APath + ANumbers.Substring(i, 1), ALen);
        }
    } /* CombinationCollocate  */-----------------------输出范例:-----------------------
    单行注释:// 排列组合
    关键字:public 关键字:void 标识符:CombinationCollocate标点符号:(标识符:List标点符号:<关键字:string标点符号:>空白: 标识符:AStrings标点符号:,空白: 关键字:string 标识符:ANumbers标点符号:,空白: 关键字:string 标识符:APath标点符号:,空白: 关键字:int 标识符:ALen标点符号:)空白:
    标点符号:{空白:
        关键字:if 标点符号:(标识符:APath标点符号:.标识符:Length空白: 标点符号:>=空白: 标识符:ALen标点符号:)空白:
        标点符号:{空白:
            标识符:AStrings标点符号:.标识符:Add标点符号:(标识符:APath标点符号:);空白:
            关键字:return标点符号:;空白:
        标点符号:}空白:
        关键字:for 标点符号:(关键字:int 标识符:i空白: 标点符号:=空白: 整数:0标点符号:;空白: 标识符:i空白: 标点符号:<空白: 标识符:ANumbers标点符号:.标识符:Length标点符号:;空白: 标识符:i标点符号:++)空白:
        标点符号:{空白:
            关键字:string 标识符:vNumbers空白: 标点符号:=空白: 标识符:ANumbers标点符号:.标识符:Remove标点符号:(标识符:i标点符号:,空白: 整数:1标点符号:);空白:
            标识符:CombinationCollocate标点符号:(标识符:AStrings标点符号:,空白: 标识符:vNumbers标点符号:,空白: 标识符:APath空白: 标点符号:+空白: 标识符:ANumbers标点符号:.标识符:Substring标点符号:(标识符:i标点符号:,空白: 整数:1标点符号:),空白: 标识符:ALen标点符号:);空白:
        标点符号:}空白:
    标点符号:}空白: 多行注释:/* CombinationCollocate  */
      

  2.   

    实际上光一个数值类型就比较复杂
    1.1
    0.1
    .01
    .1d
    1u
    1e1所以正则表达式也很难写...
      

  3.   

    zswang兄的,支持一下,先顶再看
      

  4.   

    一步一步来吧,解决一个就少一个,其实也没几个 ^v^谁帮我看看多注释的正则怎么写?
    Regex.Match(@"/* /*hello **\n\r */ /* */", @"^\/\*(?!\/\*|\*\/).*\*\/", RegexOptions.None).Value;怎么匹配成:/* /*hello **\n\r */ /* */
    理想的是:/* /*hello **\n\r */谢谢关注,路过有分,100%结贴率
      

  5.   

    在来一个,匹配关键字的
    发现上面@"(int|in|else)\s*"不能达到目的
    如果是"integer"也被匹配
    现在改成这样,不知道有没有问题:
    Regex.Match("in", @"^(int|in)(?!\w)").Value
      

  6.   

    字符串匹配也是一个问题
    主要是会出现如下情况
    string s1 = "\"";
    string s2 = @"""";
    char c = '\''
    即引号中有引号
      

  7.   

    总体来说对于C#语法,就三个关键表达式没有完成
    1、匹配数字(包括浮点数、指数表达)
    2、匹配字符串
    3、匹配多行注释大家有时间帮我想想办法
    我还得写一个语法高亮输出的引擎
    支持rtf和html格式
    敬请关注
      

  8.   

    语法高亮的部分代码,实现了rtf格式class SyntaxHighlight
    {
        public class HighlightItem
        {
            private Color FForeColor; // 前景色
            private bool FBold; // 是否加粗
            private bool FItalic; // 是否斜体
            private bool FUnderline; // 是否下划线        public Color ForeColor { get { return FForeColor; } } // 前景色
            public bool Bold { get { return FBold; } } // 是否加粗
            public bool Italic { get { return FItalic; } } // 是否斜体
            public bool Underline { get { return FUnderline; } } // 是否下划线
            public HighlightItem(Color AForeColor, bool ABold, bool AItalic, bool AUnderline)
            {
                FForeColor = AForeColor;
                FBold = ABold;
                FItalic = AItalic;
                FUnderline = AUnderline;
            }
        }
        private List<SyntaxEngine.AnalyzeReslut> FAnalyzeResluts;
        private Font FDefaultFont;
        private List<HighlightItem> FHighlightItems = new List<HighlightItem>();
        public List<HighlightItem> HighlightItems { get { return FHighlightItems; } }
        public SyntaxHighlight(SyntaxEngine ASyntaxEngine, Font 
            ADefaultFont)
        {
            FAnalyzeResluts = ASyntaxEngine.AnalyzeResluts;
            FDefaultFont = ADefaultFont;
        }    public string TextToRtf(string AText)
        {
            string vReturn = "";
            foreach (char vChar in AText)
            {
                switch (vChar)
                {
                    case '\\':
                        vReturn += @"\\";
                        break;
                    case '{':
                        vReturn += @"\{";
                        break;
                    case '}':
                        vReturn += @"\}";
                        break;
                    default:
                        if (vChar > (char)127)
                            vReturn += @"\u" + ((int)vChar).ToString() + "?";
                        else vReturn += vChar;
                        break;
                }
            }
            return vReturn;
        }
        [DllImport("user32.dll")]
        public static extern uint GetKBCodePage();
        [DllImport("kernel32.dll")]
        public static extern ushort GetSystemDefaultLangID();
        public string MakeRtf()
        {
            if (HighlightItems.Count <= 0) return "";
            string Result = @"{\rtf1\ansi\ansicpg" + GetKBCodePage().ToString() +
                @"\deff0\deflang1033\deflangfe" + GetSystemDefaultLangID().ToString() + 
                @"{\fonttbl{\f0\fmodern " + 
                FDefaultFont.Name + ";}}\r\n";
            Result += @"{\colortbl ;";
            foreach (HighlightItem vHighlightItem in HighlightItems)
                Result += string.Format(@"\red{0}\green{1}\blue{2};",
                    vHighlightItem.ForeColor.R, vHighlightItem.ForeColor.G, 
                    vHighlightItem.ForeColor.B);
            Result += "}\r\n";
            Result += @"\viewkind4\uc1\pard\f0\fs20" + "\r\n";
            bool vBold = false, vItalic = false, vUnderline = false;
            foreach (SyntaxEngine.AnalyzeReslut vAnalyzeReslut in
              FAnalyzeResluts)
            {
                int i = vAnalyzeReslut.Item.Index;
                if (i >= HighlightItems.Count) i = 0;
                if (vBold != HighlightItems[i].Bold)
                {
                    if (HighlightItems[i].Bold)
                        Result += @"\b1";
                    else Result += @"\b0";
                }
                if (vItalic != HighlightItems[i].Italic)
                {
                    if (HighlightItems[i].Italic)
                        Result += @"\i1";
                    else Result += @"\i0";
                }
                if (vItalic != HighlightItems[i].Underline)
                {
                    if (HighlightItems[i].Underline)
                        Result += @"\ul1";
                    else Result += @"\ul0";
                }
                Result += string.Format(@"\cf{0} ", i + 1);
                vBold = HighlightItems[i].Bold;
                vItalic = HighlightItems[i].Italic;
                vUnderline = HighlightItems[i].Underline;
                Result += TextToRtf(vAnalyzeReslut.Block).Replace("\r\n", 
                    "\r\n" + @"\par");
            }
            return Result + "}";
        }    public string MakeHtml()
        {
            string Result = "";
            // TODO : 
            return Result;
        }
    }class CSharpHighlight : SyntaxHighlight
    {
        public CSharpHighlight(SyntaxEngine ASyntaxEngine, Font
            ADefaultFont)
            : base(ASyntaxEngine, ADefaultFont)
        {
            //空白
            HighlightItems.Add(new HighlightItem(Color.White, false, false, false));
            //单行注释
            HighlightItems.Add(new HighlightItem(Color.Green, false, false, false));
            //多行注释
            HighlightItems.Add(new HighlightItem(Color.Green, false, false, false));
            //指令
            HighlightItems.Add(new HighlightItem(Color.Blue, false, false, false));
            //关键字
            HighlightItems.Add(new HighlightItem(Color.Black, true, false, false));
            //上下文关键字
            HighlightItems.Add(new HighlightItem(Color.Black, true, false, false));
            //标点符号
            HighlightItems.Add(new HighlightItem(Color.BlueViolet, false, false, false));
            //整数
            HighlightItems.Add(new HighlightItem(Color.Red, true, false, false));
            //十六进制数
            HighlightItems.Add(new HighlightItem(Color.Red, true, false, false));
            //字符串
            HighlightItems.Add(new HighlightItem(Color.Maroon, false, false, false));
            //字符
            HighlightItems.Add(new HighlightItem(Color.Maroon, false, false, false));
            //标识符
            HighlightItems.Add(new HighlightItem(Color.Black, false, false, false));
        }
    }
      

  9.   

    -------生成的效果如下,可以保存为rtf文件看看效果----------{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fmodern 宋体;}}
    {\colortbl ;\red255\green255\blue255;\red0\green128\blue0;\red0\green128\blue0;\red0\green0\blue255;\red0\green0\blue0;\red0\green0\blue0;\red138\green43\blue226;\red255\green0\blue0;\red255\green0\blue0;\red128\green0\blue0;\red128\green0\blue0;\red0\green0\blue0;}
    \viewkind4\uc1\pard\f0\fs20
    \cf2 // \u25490?\u21015?\u32452?\u21512?
    \par\b1\cf5 public\b0\cf1  \b1\cf5 void\b0\cf1  \cf12 CombinationCollocate\cf7 (\cf12 List\cf7 <\b1\cf5 string\b0\cf7 >\cf1  \cf12 AStrings\cf7 ,\cf1  \b1\cf5 string\b0\cf1  \cf12 ANumbers\cf7 ,\cf1  \b1\cf5 string\b0\cf1  \cf12 APath\cf7 ,\cf1  \b1\cf5 int\b0\cf1  \cf12 ALen\cf7 )\cf1 
    \par\cf7 \{\cf1 
    \par    \b1\cf5 if\b0\cf1  \cf7 (\cf12 APath\cf7 .\cf12 Length\cf1  \cf7 >=\cf1  \cf12 ALen\cf7 )\cf1 
    \par    \cf7 \{\cf1 
    \par        \cf12 AStrings\cf7 .\cf12 Add\cf7 (\cf12 APath\cf7 );\cf1 
    \par        \b1\cf5 return\b0\cf7 ;\cf1 
    \par    \cf7 \}\cf1 
    \par    \b1\cf5 for\b0\cf1  \cf7 (\b1\cf5 int\b0\cf1  \cf12 i\cf1  \cf7 =\cf1  \b1\cf8 0\b0\cf7 ;\cf1  \cf12 i\cf1  \cf7 <\cf1  \cf12 ANumbers\cf7 .\cf12 Length\cf7 ;\cf1  \cf12 i\cf7 ++)\cf1 
    \par    \cf7 \{\cf1 
    \par        \b1\cf5 string\b0\cf1  \cf12 vNumbers\cf1  \cf7 =\cf1  \cf12 ANumbers\cf7 .\cf12 Remove\cf7 (\cf12 i\cf7 ,\cf1  \b1\cf8 1\b0\cf7 );\cf1 
    \par        \cf12 CombinationCollocate\cf7 (\cf12 AStrings\cf7 ,\cf1  \cf12 vNumbers\cf7 ,\cf1  \cf12 APath\cf1  \cf7 +\cf1  \cf12 ANumbers\cf7 .\cf12 Substring\cf7 (\cf12 i\cf7 ,\cf1  \b1\cf8 1\b0\cf7 ),\cf1  \cf12 ALen\cf7 );\cf1 
    \par    \cf7 \}\cf1 
    \par\cf7 \}\cf1  \cf3 /* CombinationCollocate  */\cf1 
    \par}
      

  10.   

    11 //整数
    2d //带类型、整数(包括2f、2m)
    00098 //0开头的
    2.0 //小数
    2.0d //带类型、小数
    .1 //缺少整数、小数
    .1d //缺少整数部分、带类型、小数
    1e1d //整数、指数
    1.2e1d //小数、指数
    0x12 //十六进制数
    0x12d //十六进制数、带类型
    0x12e1d //十六进制数、指数、带类型这些数字出现的情况不知道全没?
      

  11.   

    整数
    @"^(\d+(?!\.|x|e|d)u?)|^0x([\da-f]+(?!\.|x)u?)"浮点数
    @"^(\d+)?\.\d+(e\d+)?(m|d|f)?|^\d+(e\d+)?(m|d|f)"
      

  12.   

    (\b(int)\b)|(\b(in)\b)|(\b(else)\b)(?<=[\s+\=\;\(])([\-]?\d{1,}[\.]\d{1,})|([\-]?\d{1,})(?=[\s+\=\)\;])嘻嘻~純粹湊下熱鬧。。
    正則加起來沒學到一天....
      

  13.   

    谢谢楼上,\b单词边界是该用处理字符串想到一招,就是把那些复杂组成部分一个一个吃掉
    @"^""((\\\\)*(\\"")*(\\[a-z])*[^""^\\]*)*"""
    被逼的
      

  14.   

    感谢kissknife提醒,是忘记考虑浮点数指数带符号的情况浮点数正则表达式改成这样:
    @"^(\d+)?\.\d+((\+|\-)?e\d+)?(m|d|f)?|^\d+((\+|\-)?e\d+)?(m|d|f)"关键字表达式改成这样:
    @"^(get|partial|set|value|where|yield)\b"等我加入html输出、整理后共享给大家
      

  15.   

    资源已经发布,如果大家在使用中出现什么问题和想法可以继续跟贴http://download.csdn.net/source/162229最后顶一次,晚上结了
      

  16.   

    如果是C++的就好了。
    我有别人用Delphi写的,RTF格式,基本上完美,而且可以自己定义语法规则。
      

  17.   

    正好想写个这个,就在codeproject上发现了。呵呵。
      

  18.   

    速度有点慢啊。
    XML注释能不能标记用灰色,描述才用绿色。
      

  19.   

    //在单行注释前,增加一个xml注释项
    SyntaxItems.Add(new SyntaxItem(@"^\/\/\/[^\n]*[\n]?", RegexOptions.None,
        "xml注释", SyntaxItems.Count));
    //相应位置增加,xml注释
    HighlightItems.Add(new HighlightItem(Color.Gray, false, false, false));