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

2017-09-19  本文已影响0人  UnSkyToo

因为之前的设计不合理,就重新开了工程。花了几天时间,重做的进度赶上之前的了
今天来说说分析源代码
源码分析中会用到的其它东西,之前都介绍过了。
接下来看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()就能分析完整个代码

上一篇 下一篇

猜你喜欢

热点阅读