自己动手设计代码编辑器——(五)分析源代码

来源:互联网 发布:大数据底层开发工程师 编辑:程序博客网 时间:2024/04/29 14:53

因为之前的设计不合理,就重新开了工程。花了几天时间,重做的进度赶上之前的了


今天来说说分析源代码


源码分析中会用到的其它东西,之前都介绍过了。

接下来看UParser这个类中最后的函数GetNextCut,是用来把源码分析为UCodeCut集合的。其中包括关键字设别,变量设别等等


开始

UCodeCut cut = new UCodeCut();List<byte> cutData = new List<byte>();byte b;UCutType currType = UCutType.None; // 状态机的状态bool inString = false; // 是否解析字符串if (EndOfCode == true){cut.CutType = UCutType.End;return cut;}


开头就是定义一些变量,并且判断分析是否结束

cut用于保存分析玩的CodeCut

cutData是cut中的具体数据

currType是当前状态机的状态

接下来是状态机的循环

while (!EndOfCode){b = GetNextByte();cutData.Add(b);......}

然后是状态机的入口

#region UCutType.None                    if (currType == UCutType.None)                    {                        if (b == UConfig.Space)                        {                            currType = UCutType.Space;                            continue;                        }                        if (b == UConfig.Tab)                        {                            currType = UCutType.Tab;                            break;                        }                        if (b == UConfig.DoubleQuote)                        {                            currType = UCutType.String;                            inString = true;                            continue;                        }                        if (b == UConfig.NewLine)                        {                            currType = UCutType.NewLine;                            // 跳过回车符                            if (PeekNextByte() == UConfig.Enter)                            {                                GetNextByte();                            }                            break;                        }                        if (b == UConfig.BackSlash)                        {                            if (PeekNextByte() == UConfig.BackSlash)                            {                                currType = UCutType.Annotation;                                continue;                            }                        }                        if (UHelper.IsSymbol(b))                        {                            currType = UCutType.Symbol;                            break;                        }                        if (UHelper.IsCharacter(b))                        {                            currType = UCutType.Normal;                            continue;                        }                        if (UHelper.IsDigit(b))                        {                            currType = UCutType.Digit;                            continue;                        }                    }                    #endregion


接下来是Normal状态,就是一些普通的字符串

#region UCutType.Normal                    if (currType == UCutType.Normal)                    {                        if (UHelper.IsCutEnd(b))                        {                            BackToLastByte();                            cutData.RemoveAt(cutData.Count - 1);                            break;                        }                    }                    #endregion

接下来是String状态,是字符串

#region UCutType.String                    if (currType == UCutType.String)                    {                        if (b == UConfig.NewLine)                        {                            BackToLastByte();                            currType = UCutType.Normal;                            break;                        }                        if (b == UConfig.DoubleQuote)                        {                            inString = false;                            break;                        }                        if (b == UConfig.Slash)                        {                            // 添加 \ 后的字符                            if (inString)                            {                                //ch = (char)GetNextChar();                                //cutData.Add((byte)ch);                                cutData.Add(GetNextByte());                                continue;                            }                        }                    }                    #endregion

接下来  数字状态、注释等等,都一样的判断格式


最后循环结束,检查关键字

// 替换Tab为Space                if (currType == UCutType.Tab)                {                    cut.Data = UConfig.TabString;                    cut.CutType = UCutType.Space;                }                else                {                    cut.Data = UHelper.GetStringByBytes(cutData.ToArray());                    cut.CutType = currType;                                        // 如果是普通的一段文本,判断是否为关键字                    if (currType == UCutType.Normal)                    {                        if (UHelper.IsKeyWord(cut.Data))                        {                            cut.CutType = UCutType.KeyWord;                        }                    }                }

最后检查,是否为变量或者类

if (currType == UCutType.Normal)                {                    if (LastCut2.CutType == UCutType.KeyWord && LastCut1.CutType == UCutType.Space)                    {                        // 类的定义                        if (LastCut2.Data == UConfig.ClassString)                        {                            cut.CutType = UCutType.ClassName;                        }                        else                        {                            // 函数名的定义                            foreach (string str in UConfig.FunctionDefineString)                            {                                if (str == LastCut2.Data)                                {                                    if (PeekNextByte() == (byte)'(')                                    {                                        cut.CutType = UCutType.FunctionName;                                    }                                    else                                    {                                        cut.CutType = UCutType.VariableName;                                    }                                    break;                                }                            }                        }                    }                }                LastCut2 = LastCut1;                LastCut1 = cut;

这就是一个CodeCut的分析过程了


接下来只要不断的调用GetNextCut()就能分析完整个代码


原创粉丝点击