• (转)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. }


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

  • 相关阅读:
    大型网站应用中MySQL的架构演变史
    SRM 585 DIV2
    TC 配置插件
    Java中含有静态成员的的初始化顺序
    java 23种设计模式,一般情况下,常用的有哪些? 转载
    Java中的正则表达式
    C++ 中的关于输出的设置于
    C++实现可变参数列表
    Java中的组合与聚合
    pku 2284 That Nice Euler Circuit
  • 原文地址:https://www.cnblogs.com/liuhaili/p/2210986.html
Copyright © 2020-2023  润新知