lambda表達式的解析(三) 類型轉換表達式

接 上篇的常量表達式的轉換,接下來要講的是怎麼產生操作運算表達式。

和C#通常意義上的3種操作符不同,我們的grammar把類型轉換操作()從unary expression裏拿出來獨立成一個typecast_expression,也就是說要轉換的操作符節點有4種。而且對於unary expression來說也有特別的地方,++,-- 這2個操作符不屬於unray_operator下,grammar是把它們獨立成pre_incr_decr_expression和post_incr_decr_expression 2塊單獨處理。還有就是在C#裏as這個操作符是被定義成一元的,而我們的grammar則視它爲二元操作符。

類型轉換的操作很簡單,這是grammar樹: 

在這裏是做了一個int到int?的強類型轉換,所以可以看type_ref裏有一個qmark_opt,這表明是個nullable類型。

轉換入口:

                case "typecast_expression":
                    return ProcessConvertExpression(expNode);

具體轉換代碼:

        private Expression ProcessConvertExpression(ParseTreeNode expNode)
        {
            var type = expNode.GetChild("typecast_parenthesized_expression").GetClrType();
            var exp = ProcessExpression(expNode.GetChild("primary_expression"));
            return Expression.Convert(exp, type);
        }

可以看到這裏爲了取到要被強類型轉換的對象,採用了遞歸調用ProcssExpression處理方式,而子節點裏是一個literal,所以子節點會返回一個ConstantExpression。而GetClrType是treenode的擴展方法,它的代碼在第一章裏有提到。

        public static Type GetClrType(this ParseTreeNode node)
        {
            if (node.HasChild("type_ref"))
            {
                var isNullable = node.GetDescendant("qmark_opt").FindTokenAndGetText() == "?";
                var typeName = node.FindTokenAndGetText();
                var type = ExpressionParser.GetType(typeName);
                if (isNullable)
                    return typeof(Nullable<>).MakeGenericType(type);
                return type;
            }
            return null;
        }


就是根據type_ref子節點返回正確的clr類型。其中ExpressionParser.GetType方法如下:

        internal static Type GetType(string typeName)
        {
            var type = Type.GetType(typeName);
            if (type == null)
                knownTypes.TryGetValue(typeName, out type);
            return type;
        }


就是通過typename得到Type,這裏要注意的是int、char、string這些內建類型的名字並不是int、char、string,所以會有個knownTypes表來幫助返回正確的類型:

        private static ConcurrentDictionary<string, Type> knownTypes = new ConcurrentDictionary<string, Type>();

            #region BuiltinTypes
            knownTypes["bool"] = typeof(bool);
            knownTypes["sbyte"] = typeof(sbyte);
            knownTypes["byte"] = typeof(byte);
            knownTypes["short"] = typeof(short);
            knownTypes["ushort"] = typeof(ushort);
            knownTypes["int"] = typeof(int);
            knownTypes["uint"] = typeof(uint);
            knownTypes["long"] = typeof(long);
            knownTypes["ulong"] = typeof(ulong);
            knownTypes["float"] = typeof(float);
            knownTypes["double"] = typeof(double);
            knownTypes["char"] = typeof(char);
            knownTypes["string"] = typeof(string);
            knownTypes["decimal"] = typeof(decimal);
            knownTypes["object"] = typeof(object);
            knownTypes["void"] = typeof(void);
            #endregion

正確的類型和正確的對象,創建個ConvertExpression也就非常簡單了



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章