(转)lambda表达式的解析(三) 类型转换表达式

本文详细阐述了如何在语法解析中实现强类型转换,并介绍了操作运算表达式的生成过程,包括特殊操作符的处理及C#与语法解析器间的区别。重点在于展示类型转换表达式的独立处理方式及如何利用递归调用处理复杂类型转换。

接 上篇的常量表达式的转换,接下来要讲的是怎么产生操作运算表达式。

和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);

case "typecast_expression": 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. }

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的扩展方法,它的代码在第一章里有提到。

  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. }

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方法如下:

  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. }

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表来帮助返回正确的类型:

  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

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也就非常简单了

转载于:https://www.cnblogs.com/liuhaili/archive/2011/10/13/2210985.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值