(转)lambda表达式的解析(四) 运算符表达式

一元、二元、三元运算符的转换大多都非常有规律,先看这个一元树:

主要就是一个运算符跟一个表达式,转换起来很简单:

  1. private Expression ProcessUnaryExpression(ParseTreeNode expNode)
  2. {
  3. string op;
  4. var first = expNode.FirstChild;
  5. var second = expNode.LastChild;
  6. switch (first.GetName())
  7. {
  8. case "unary_operator":
  9. op = first.FirstChild.GetValue();
  10. break;
  11. case "pre_incr_decr_expression":
  12. op = first.GetChild("incr_or_decr").FirstChild.GetValue();
  13. second = first.LastChild;
  14. break;
  15. case "post_incr_decr_expression":
  16. op = "post" + first.GetChild("incr_or_decr").FirstChild.GetValue();
  17. second = first.FirstChild;
  18. break;
  19. default:
  20. return ProcessExpression(expNode.FirstChild);
  21. }
  22. return Expression.MakeUnary(unaryOps[op], ProcessExpression(second), null);
  23. }


运算符表:

  1. #region UnaryOps
  2. unaryOps["++"] = ExpressionType.PreIncrementAssign;
  3. unaryOps["--"] = ExpressionType.PreDecrementAssign;
  4. unaryOps["post++"] = ExpressionType.PostIncrementAssign;
  5. unaryOps["post--"] = ExpressionType.PostDecrementAssign;
  6. unaryOps["!"] = ExpressionType.Not;
  7. unaryOps["~"] = ExpressionType.Not;
  8. unaryOps["+"] = ExpressionType.Quote;
  9. unaryOps["-"] = ExpressionType.Negate;
  10. //ops["as"] = ExpressionType.TypeAs;
  11. #endregion

如前一篇提到的,要注意的有2点,第一是++,--的节点是独立出来的需要特殊处理,第二就是as在C#里虽然是一元的但我们的grammar视其为二元所以不在这里处理。

还有就是MakeUnary的第三个参数是表达式返回类型,从优化角度考虑这个参数在某些情况下可以直接代替ConvertExpression,从而节省一个节点,目前不考虑优化情况下忽略了这个参数。

二元和三元处理方式都类似,二元的树:

这个图里面也包括了++,--这个特别节点的显示方式,可以清晰的看出前面一元处理方法是怎么处理的。

二元处理方法:

  1. private Expression ProcessBinaryExpression(ParseTreeNode expNode)
  2. {
  3. var left = expNode.ChildNodes[0];
  4. var right = expNode.ChildNodes[2];
  5. var op = expNode.ChildNodes[1].FirstChild.GetValue();
  6. if (op == "as")
  7. {
  8. var typeName = right.GetDescendant("Identifier").GetValue();
  9. return Expression.TypeAs(ProcessExpression(left), GetType(typeName));
  10. }
  11. return Expression.MakeBinary(binaryOps[op], ProcessExpression(left), ProcessExpression(right));
  12. }


二元运算符表:

  1. #region BinaryOps
  2. binaryOps["+"] = ExpressionType.Add;
  3. binaryOps["-"] = ExpressionType.Subtract;
  4. binaryOps["*"] = ExpressionType.Multiply;
  5. binaryOps["/"] = ExpressionType.Divide;
  6. binaryOps["%"] = ExpressionType.Modulo;
  7. binaryOps["&"] = ExpressionType.And;
  8. binaryOps["|"] = ExpressionType.Or;
  9. binaryOps["^"] = ExpressionType.ExclusiveOr;
  10. binaryOps["??"] = ExpressionType.Coalesce;
  11. binaryOps["<<"] = ExpressionType.LeftShift;
  12. binaryOps[">>"] = ExpressionType.RightShift;
  13. binaryOps["+="] = ExpressionType.AddAssign;
  14. binaryOps["-="] = ExpressionType.SubtractAssign;
  15. binaryOps["*="] = ExpressionType.MultiplyAssign;
  16. binaryOps["/="] = ExpressionType.DivideAssign;
  17. binaryOps["%="] = ExpressionType.ModuloAssign;
  18. binaryOps["&="] = ExpressionType.AndAssign;
  19. binaryOps["|="] = ExpressionType.OrAssign;
  20. binaryOps["^="] = ExpressionType.ExclusiveOrAssign;
  21. binaryOps["<<="] = ExpressionType.LeftShiftAssign;
  22. binaryOps[">>="] = ExpressionType.RightShiftAssign;
  23. binaryOps["=="] = ExpressionType.Equal;
  24. binaryOps["!="] = ExpressionType.NotEqual;
  25. binaryOps["&&"] = ExpressionType.AndAlso;
  26. binaryOps["||"] = ExpressionType.OrElse;
  27. binaryOps["is"] = ExpressionType.TypeIs;
  28. binaryOps["="] = ExpressionType.Equal;
  29. #endregion


和前面提到的一样,二元处理方法里特别照顾了as操作。

三元条件表达式的图:

处理方法:

  1. private Expression ProcessConditionalExpression(ParseTreeNode expNode)
  2. {
  3. return Expression.Condition(
  4. ProcessExpression(expNode.FirstChild),
  5. ProcessExpression(expNode.ChildNodes[2]),
  6. ProcessExpression(expNode.ChildNodes[3]));
  7. }


运算符表达式的解析处理都很类似,简单明了的很,所以这里就不再进一步赘述了。

posted @ 2011-10-13 22:46  小芒果  阅读(406)  评论(0编辑  收藏  举报