(转)lambda表达式的解析(四) 运算符表达式
2011-10-13 22:46
417 查看
一元、二元、三元运算符的转换大多都非常有规律,先看这个一元树:
主要就是一个运算符跟一个表达式,转换起来很简单:
view plaincopy to clipboardprint?
private Expression ProcessUnaryExpression(ParseTreeNode expNode)
{
string op;
var first = expNode.FirstChild;
var second = expNode.LastChild;
switch (first.GetName())
{
case "unary_operator":
op = first.FirstChild.GetValue();
break;
case "pre_incr_decr_expression":
op = first.GetChild("incr_or_decr").FirstChild.GetValue();
second = first.LastChild;
break;
case "post_incr_decr_expression":
op = "post" + first.GetChild("incr_or_decr").FirstChild.GetValue();
second = first.FirstChild;
break;
default:
return ProcessExpression(expNode.FirstChild);
}
return Expression.MakeUnary(unaryOps[op], ProcessExpression(second), null);
}
如前一篇提到的,要注意的有2点,第一是++,--的节点是独立出来的需要特殊处理,第二就是as在C#里虽然是一元的但我们的grammar视其为二元所以不在这里处理。
还有就是MakeUnary的第三个参数是表达式返回类型,从优化角度考虑这个参数在某些情况下可以直接代替ConvertExpression,从而节省一个节点,目前不考虑优化情况下忽略了这个参数。
二元和三元处理方式都类似,二元的树:
这个图里面也包括了++,--这个特别节点的显示方式,可以清晰的看出前面一元处理方法是怎么处理的。
二元处理方法:
view plaincopy to clipboardprint?
private Expression ProcessBinaryExpression(ParseTreeNode expNode)
{
var left = expNode.ChildNodes[0];
var right = expNode.ChildNodes[2];
var op = expNode.ChildNodes[1].FirstChild.GetValue();
if (op == "as")
{
var typeName = right.GetDescendant("Identifier").GetValue();
return Expression.TypeAs(ProcessExpression(left), GetType(typeName));
}
return Expression.MakeBinary(binaryOps[op], ProcessExpression(left), ProcessExpression(right));
}
和前面提到的一样,二元处理方法里特别照顾了as操作。
三元条件表达式的图:
处理方法:
view plaincopy to clipboardprint?
private Expression ProcessConditionalExpression(ParseTreeNode expNode)
{
return Expression.Condition(
ProcessExpression(expNode.FirstChild),
ProcessExpression(expNode.ChildNodes[2]),
ProcessExpression(expNode.ChildNodes[3]));
}
private Expression ProcessConditionalExpression(ParseTreeNode expNode)
{
return Expression.Condition(
ProcessExpression(expNode.FirstChild),
ProcessExpression(expNode.ChildNodes[2]),
ProcessExpression(expNode.ChildNodes[3]));
}
运算符表达式的解析处理都很类似,简单明了的很,所以这里就不再进一步赘述了。
主要就是一个运算符跟一个表达式,转换起来很简单:
view plaincopy to clipboardprint?
private Expression ProcessUnaryExpression(ParseTreeNode expNode)
{
string op;
var first = expNode.FirstChild;
var second = expNode.LastChild;
switch (first.GetName())
{
case "unary_operator":
op = first.FirstChild.GetValue();
break;
case "pre_incr_decr_expression":
op = first.GetChild("incr_or_decr").FirstChild.GetValue();
second = first.LastChild;
break;
case "post_incr_decr_expression":
op = "post" + first.GetChild("incr_or_decr").FirstChild.GetValue();
second = first.FirstChild;
break;
default:
return ProcessExpression(expNode.FirstChild);
}
return Expression.MakeUnary(unaryOps[op], ProcessExpression(second), null);
}
view plaincopy to clipboardprint? #region UnaryOps unaryOps["++"] = ExpressionType.PreIncrementAssign; unaryOps["--"] = ExpressionType.PreDecrementAssign; unaryOps["post++"] = ExpressionType.PostIncrementAssign; unaryOps["post--"] = ExpressionType.PostDecrementAssign; unaryOps["!"] = ExpressionType.Not; unaryOps["~"] = ExpressionType.Not; unaryOps["+"] = ExpressionType.Quote; unaryOps["-"] = ExpressionType.Negate; //ops["as"] = ExpressionType.TypeAs; #endregion #region UnaryOps unaryOps["++"] = ExpressionType.PreIncrementAssign; unaryOps["--"] = ExpressionType.PreDecrementAssign; unaryOps["post++"] = ExpressionType.PostIncrementAssign; unaryOps["post--"] = ExpressionType.PostDecrementAssign; unaryOps["!"] = ExpressionType.Not; unaryOps["~"] = ExpressionType.Not; unaryOps["+"] = ExpressionType.Quote; unaryOps["-"] = ExpressionType.Negate; //ops["as"] = ExpressionType.TypeAs; #endregion
如前一篇提到的,要注意的有2点,第一是++,--的节点是独立出来的需要特殊处理,第二就是as在C#里虽然是一元的但我们的grammar视其为二元所以不在这里处理。
还有就是MakeUnary的第三个参数是表达式返回类型,从优化角度考虑这个参数在某些情况下可以直接代替ConvertExpression,从而节省一个节点,目前不考虑优化情况下忽略了这个参数。
二元和三元处理方式都类似,二元的树:
这个图里面也包括了++,--这个特别节点的显示方式,可以清晰的看出前面一元处理方法是怎么处理的。
二元处理方法:
view plaincopy to clipboardprint?
private Expression ProcessBinaryExpression(ParseTreeNode expNode)
{
var left = expNode.ChildNodes[0];
var right = expNode.ChildNodes[2];
var op = expNode.ChildNodes[1].FirstChild.GetValue();
if (op == "as")
{
var typeName = right.GetDescendant("Identifier").GetValue();
return Expression.TypeAs(ProcessExpression(left), GetType(typeName));
}
return Expression.MakeBinary(binaryOps[op], ProcessExpression(left), ProcessExpression(right));
}
view plaincopy to clipboardprint? #region BinaryOps binaryOps["+"] = ExpressionType.Add; binaryOps["-"] = ExpressionType.Subtract; binaryOps["*"] = ExpressionType.Multiply; binaryOps["/"] = ExpressionType.Divide; binaryOps["%"] = ExpressionType.Modulo; binaryOps["&"] = ExpressionType.And; binaryOps["|"] = ExpressionType.Or; binaryOps["^"] = ExpressionType.ExclusiveOr; binaryOps["??"] = ExpressionType.Coalesce; binaryOps["<<"] = ExpressionType.LeftShift; binaryOps[">>"] = ExpressionType.RightShift; binaryOps["+="] = ExpressionType.AddAssign; binaryOps["-="] = ExpressionType.SubtractAssign; binaryOps["*="] = ExpressionType.MultiplyAssign; binaryOps["/="] = ExpressionType.DivideAssign; binaryOps["%="] = ExpressionType.ModuloAssign; binaryOps["&="] = ExpressionType.AndAssign; binaryOps["|="] = ExpressionType.OrAssign; binaryOps["^="] = ExpressionType.ExclusiveOrAssign; binaryOps["<<="] = ExpressionType.LeftShiftAssign; binaryOps[">>="] = ExpressionType.RightShiftAssign; binaryOps["=="] = ExpressionType.Equal; binaryOps["!="] = ExpressionType.NotEqual; binaryOps["&&"] = ExpressionType.AndAlso; binaryOps["||"] = ExpressionType.OrElse; binaryOps["is"] = ExpressionType.TypeIs; binaryOps["="] = ExpressionType.Equal; #endregion #region BinaryOps binaryOps["+"] = ExpressionType.Add; binaryOps["-"] = ExpressionType.Subtract; binaryOps["*"] = ExpressionType.Multiply; binaryOps["/"] = ExpressionType.Divide; binaryOps["%"] = ExpressionType.Modulo; binaryOps["&"] = ExpressionType.And; binaryOps["|"] = ExpressionType.Or; binaryOps["^"] = ExpressionType.ExclusiveOr; binaryOps["??"] = ExpressionType.Coalesce; binaryOps["<<"] = ExpressionType.LeftShift; binaryOps[">>"] = ExpressionType.RightShift; binaryOps["+="] = ExpressionType.AddAssign; binaryOps["-="] = ExpressionType.SubtractAssign; binaryOps["*="] = ExpressionType.MultiplyAssign; binaryOps["/="] = ExpressionType.DivideAssign; binaryOps["%="] = ExpressionType.ModuloAssign; binaryOps["&="] = ExpressionType.AndAssign; binaryOps["|="] = ExpressionType.OrAssign; binaryOps["^="] = ExpressionType.ExclusiveOrAssign; binaryOps["<<="] = ExpressionType.LeftShiftAssign; binaryOps[">>="] = ExpressionType.RightShiftAssign; binaryOps["=="] = ExpressionType.Equal; binaryOps["!="] = ExpressionType.NotEqual; binaryOps["&&"] = ExpressionType.AndAlso; binaryOps["||"] = ExpressionType.OrElse; binaryOps["is"] = ExpressionType.TypeIs; binaryOps["="] = ExpressionType.Equal; #endregion
和前面提到的一样,二元处理方法里特别照顾了as操作。
三元条件表达式的图:
处理方法:
view plaincopy to clipboardprint?
private Expression ProcessConditionalExpression(ParseTreeNode expNode)
{
return Expression.Condition(
ProcessExpression(expNode.FirstChild),
ProcessExpression(expNode.ChildNodes[2]),
ProcessExpression(expNode.ChildNodes[3]));
}
private Expression ProcessConditionalExpression(ParseTreeNode expNode)
{
return Expression.Condition(
ProcessExpression(expNode.FirstChild),
ProcessExpression(expNode.ChildNodes[2]),
ProcessExpression(expNode.ChildNodes[3]));
}
运算符表达式的解析处理都很类似,简单明了的很,所以这里就不再进一步赘述了。
相关文章推荐
- lambda表达式的解析(四) 运算符表达式
- C++11 lambda 表达式解析
- python函数,lambda表达式,三目运算,列表解析,递归
- (转)lambda表达式的解析(三) 类型转换表达式
- C++11 lambda 表达式解析
- 对lambda表达式的解析(二)
- C# 新委托使用方法 Lambda表达式,运算符 =>
- C++11 lambda 表达式解析
- (转)lambda表达式的解析(五) Lambda表达式与闭包类型
- 解析 Lambda 表达式
- (转)lambda表达式的解析(六) 成员访问表达式
- 深入解析Python中的lambda表达式的用法
- C++11 lambda 表达式解析
- lambda表达式的解析(五) Lambda表达式与闭包类型
- C++11 lambda 表达式解析
- JDK 8 Lambda 表达式解析Map和List
- C++11 lambda 表达式解析
- C++11 lambda 表达式解析
- (转)lambda表达式的解析(七) 对象的创建
- C++11 lambda 表达式解析