您的位置:首页 > 其它

(转)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);

}

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]));
}

运算符表达式的解析处理都很类似,简单明了的很,所以这里就不再进一步赘述了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: