C语言解释器-7 一切的基础 Context类

来源:互联网 发布:linux 线程 参数 编辑:程序博客网 时间:2024/06/13 23:11

Context是构建语法树的基础,程序由一个个Context组成,比如变量(申明),语句,块,函数,控制结构等。

看看Context类的Run方法,很能说明问题:

public virtual void Run(Context ctx)        {            // 正在运行标记            IsRunning = true;                        foreach (Context stx in Children)            {                try                {                    if (stx is Statement || stx is Block)                    {                        stx.Run(this);                    }                    else                        if (stx is Variable)                        {                            //局部变量,需要登记,以便将来释放                            LocalVariables.Add(stx.Name);                            stx.Run(this);                        }                        else                            if (stx is ConstantInitialize)                            {                                //常量,出现在全局Context中,需要记录。在运行到最后的时候释放                                m_constantVariableDict.Add((stx as ConstantInitialize).VariableName, stx);                                stx.Run(this);                            }                            else                                if (stx is Function.FunctionDefine)                                {                                    // 仅运行main函数,其他函数在调用时运行                                    if (stx.Name == MainFunctionName)                                    {                                        m_mainFunction = stx as Function.FunctionDefine;                                        m_mainFunction.Body.Run(this);                                    }                                }                }                catch (RuntimeException re)                {                    if (OnRuntimeError != null)                        OnRuntimeError(stx, re.Message);                }            } // foreach            // 释放局部变量            FreeLocalVariables();            IsRunning = false;        }


设定所有的Context都应该有个Parent,如果Parent为null,则表示为全局的Context。也即Yacc脚本中的Program规则。

主要的属性有:

// Public        public Context Parent;        public List<Context> Children;        public string Name;        public List<string> LocalVariables;        public bool IsFirstRunning = true;        public LocationInfo Location;        public event EventHandler<string> OnRuntimeError;

 

一些全局性的东西,申明为静态,主要与语法分析相关。还包括内部定义函数。

// Static        public static string MainFunctionName = "main";        private static int AnonymousVariableCount = 0;        private static string AnonymousVariableNamePrefix = "var";        private static bool ContextIsRunning = false;                public static Dictionary<string, bool> KeywordDict = new Dictionary<string, bool>();        public static Dictionary<string, PrimitiveDataType> DataTypeKeywordDict = new Dictionary<string, PrimitiveDataType>();        public static Dictionary<string, bool> ControlKeywordDict = new Dictionary<string, bool>();        public static Dictionary<int, short> TypeCombinationDict = new Dictionary<int, short>();        public static Dictionary<string, bool> InternalFunctionDict = new Dictionary<string, bool>();        public static Memory Memory = new Memory("");        public static bool IsRunning        {            get { return ContextIsRunning; }            protected set { ContextIsRunning = value; }        }        public static string GetAnonymousName()        {            return string.Format("${0}_{1}$", AnonymousVariableNamePrefix, ++AnonymousVariableCount);        }        public static string GetAnonymousName(string prefix)        {            return string.Format("${0}_{1}$", prefix, ++AnonymousVariableCount);        }        public static string GetAnonymousName(DataTypeInfo dti)        {            return string.Format("${0}_{1}_{2}{3}$",                 AnonymousVariableNamePrefix,                 DataTypeInfo.StringFromType(dti.BaseType),                dti.PointerCount > 0 ? "ptr_" : "",                ++AnonymousVariableCount);        }        public static bool IsKeyword(string str)        {            if (KeywordDict.Count == 0)            {                // primitive type                KeywordDict.Add("void", true);                KeywordDict.Add("char", true);                KeywordDict.Add("short", true);                KeywordDict.Add("int", true);                KeywordDict.Add("float", true);                KeywordDict.Add("signed", true);                KeywordDict.Add("unsigned", true);                // control                KeywordDict.Add("if", true);                KeywordDict.Add("else", true);                KeywordDict.Add("for", true);                KeywordDict.Add("do", true);                KeywordDict.Add("while", true);                KeywordDict.Add("switch", true);                KeywordDict.Add("case", true);                KeywordDict.Add("continue", true);                KeywordDict.Add("break", true);                KeywordDict.Add("return", true);                // misc                KeywordDict.Add("sizeof", true);            }            return KeywordDict.ContainsKey(str);        }        public static bool IsDataType(string str)        {            if (DataTypeKeywordDict.Count == 0)            {                DataTypeKeywordDict.Add("void", PrimitiveDataType.VoidType);                DataTypeKeywordDict.Add("char", PrimitiveDataType.CharType);                DataTypeKeywordDict.Add("short", PrimitiveDataType.ShortType);                DataTypeKeywordDict.Add("int", PrimitiveDataType.IntType);                DataTypeKeywordDict.Add("float", PrimitiveDataType.FloatType);                DataTypeKeywordDict.Add("signed", PrimitiveDataType.SignedType);                DataTypeKeywordDict.Add("unsigned", PrimitiveDataType.UnsignedType);            }            return DataTypeKeywordDict.ContainsKey(str);        }        public static bool IsControlFlow(string str)        {            if (ControlKeywordDict.Count == 0)            {                ControlKeywordDict.Add("if", true);                ControlKeywordDict.Add("else", true);                ControlKeywordDict.Add("for", true);                ControlKeywordDict.Add("do", true);                ControlKeywordDict.Add("while", true);                ControlKeywordDict.Add("switch", true);                ControlKeywordDict.Add("case", true);                ControlKeywordDict.Add("continue", true);                ControlKeywordDict.Add("break", true);                ControlKeywordDict.Add("return", true);            }            return ControlKeywordDict.ContainsKey(str);        }        public static bool IsInternalFunction(string str)        {            return InternalFunctionDict.ContainsKey(str);        }        public static void RegisterInternalFunction(string name)        {            if (!InternalFunctionDict.ContainsKey(name))                InternalFunctionDict.Add(name, true);        }


注意到相当多的静态方法使用字符串字典。

 

另外一个重要的方法是FindByName(string name),该方法用于查找符合指定名字的已定义的Context,这是检查或查找变量、函数的重要手段。

public virtual Context FindByName(string str)        {            if (m_nameDict.ContainsKey(str))                return m_nameDict[str];            Context stx = this.Parent;            if (stx != null)                return stx.FindByName(str);            return null;        }


一些语法结构,如控制结构、函数,需要知道一些额外信息,因此需要以下辅助方法:

public bool IsInFunction        {            get            {                Context stx = Parent;                while (stx != null)                {                    if (stx is Function.FunctionDefine)                        return true;                    stx = stx.Parent;                 }                return false;            }        }        public Function.FunctionDefine ParentFunction        {            get            {                Context stx = Parent;                while (stx != null)                {                    if (stx is Function.FunctionDefine)                        return stx as Function.FunctionDefine;                    stx = stx.Parent;                }                return null;            }        }        public Block ParentBlock        {            get            {                Context stx = Parent;                while (stx != null)                {                    if (stx is Block)                        return stx as Block;                    stx = stx.Parent;                }                return null;            }        }        public bool IsInLoop        {            get            {                Context stx = Parent;                while (stx != null)                {                    if (stx is ControlFlow.ForLoop || stx is ControlFlow.DoWhileLoop || stx is ControlFlow.WhileLoop)                        return true;                    stx = stx.Parent;                }                return false;            }        }        public bool IsInSwitch        {            get            {                Context stx = this;                while (stx != null)                {                    if (stx is ControlFlow.Switch)                        return true;                    stx = stx.Parent;                }                return false;            }        }        public Context GlobalContex        {            get            {                if (this.Parent == null)                    return this;                else                    return this.Parent.GlobalContex;            }        }


常量应该在最后一刻释放。相同的还有函数的参数定义。SharpC将函数的参数视为特殊的局部变量:在函数第一次运行时分配空间,而在解释器运行到最后时才释放。也算是一种简单的优化。

~Context()        {            FreeConstantVariables();            if (Parent == null)            {                if (m_mainFunction != null)                    FreeFunctionArguments(m_mainFunction);                FreeAllFunctionArguments(this);            }        }