zoukankan      html  css  js  c++  java
  • (转)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类型。

    转换入口:

    1. case "typecast_expression":
    2. return ProcessConvertExpression(expNode);

    具体转换代码:

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

    可以看到这里为了取到要被强类型转换的对象,采用了递归调用ProcssExpression处理方式,而子节点里是一个literal,所以子节点会返回一个ConstantExpression。而GetClrType是treenode的扩展方法,它的代码在第一章里有提到。

    1. public static Type GetClrType(this ParseTreeNode node)
    2. {
    3. if (node.HasChild("type_ref"))
    4. {
    5. var isNullable = node.GetDescendant("qmark_opt").FindTokenAndGetText() == "?";
    6. var typeName = node.FindTokenAndGetText();
    7. var type = ExpressionParser.GetType(typeName);
    8. if (isNullable)
    9. return typeof(Nullable<>).MakeGenericType(type);
    10. return type;
    11. }
    12. return null;
    13. }


    就是根据type_ref子节点返回正确的clr类型。其中ExpressionParser.GetType方法如下:

    1. internal static Type GetType(string typeName)
    2. {
    3. var type = Type.GetType(typeName);
    4. if (type == null)
    5. knownTypes.TryGetValue(typeName, out type);
    6. return type;
    7. }


    就是通过typename得到Type,这里要注意的是int、char、string这些内建类型的名字并不是int、char、string,所以会有个knownTypes表来帮助返回正确的类型:

    1. private static ConcurrentDictionary<string, Type> knownTypes = new ConcurrentDictionary<string, Type>();
    2. #region BuiltinTypes
    3. knownTypes["bool"] = typeof(bool);
    4. knownTypes["sbyte"] = typeof(sbyte);
    5. knownTypes["byte"] = typeof(byte);
    6. knownTypes["short"] = typeof(short);
    7. knownTypes["ushort"] = typeof(ushort);
    8. knownTypes["int"] = typeof(int);
    9. knownTypes["uint"] = typeof(uint);
    10. knownTypes["long"] = typeof(long);
    11. knownTypes["ulong"] = typeof(ulong);
    12. knownTypes["float"] = typeof(float);
    13. knownTypes["double"] = typeof(double);
    14. knownTypes["char"] = typeof(char);
    15. knownTypes["string"] = typeof(string);
    16. knownTypes["decimal"] = typeof(decimal);
    17. knownTypes["object"] = typeof(object);
    18. knownTypes["void"] = typeof(void);
    19. #endregion

    正确的类型和正确的对象,创建个ConvertExpression也就非常简单了

  • 相关阅读:
    【剑指offer】07重建二叉树,C++实现
    【剑指offer】06从尾到头打印链表,C++实现
    面向对象设计模式原则01 开闭原则(OCP)
    面向对象设计模式原则02 里氏替换原则(LSP)
    面向对象设计模式原则03 依赖倒置原则(DIP)
    面向对象设计模式原则05 接口隔离原则(ISP)
    面向对象设计模式原则04 单一职责原则(SRP)
    leetcode1218
    leetcode1232
    leetcode1228
  • 原文地址:https://www.cnblogs.com/liuhaili/p/2210985.html
Copyright © 2011-2022 走看看