作者SDNiceBoat (NiceBoat.)
看板C_Sharp
标题[问题] 语法树的设计.... 树打结了....
时间Mon Aug 23 23:01:04 2010
可以把任何执行式写成「树」
例如:
Math.Atan2(Math.Max(1.1,1.0),Math.Pow(Math.Min(2,Math.E),Math.PI));
就变成
http://ppt.cc/@SRy
这在观念上没有问题
如果要对整株树做些什麽特殊的事情
只要呼叫子层的方法,子层再去呼叫子层就好
简单来讲,就是递回
======================================================================
因为C#不提供先把参数塞进委派,到要执行的时候才去执行的功能
所以自己写了一些小工具来用
当然,用到一点语法树的观念。
大致上是像这种东西:
public sealed class ActOrVal<Tout> : ACT<Tout>
{
private Func<Tout> 执行式;
private Tout 数值;
public override Tout GetValue()
{
if (this.执行式 == null) return this.数值;
return this.执行式();
//如果存放的是委派,传回执行後得到的值
//如果放的是参数,则传回参数
}
public override ACT<Tout> Get副本()
{
if (this.执行式 == null) return new ActOrVal<Tout>(this.数值);
return new ActOrVal<Tout>(this.执行式);
}
}
public sealed class ActOrVal<Tin1, Tout> : ACT<Tout>
{
private ACT<Func<Tin1,Tout>> 执行式2;
public override Tout GetValue()
{
return this.执行式2.GetValue()((Tin1)this.执行参数);
//把参数塞进委派里,并执行它,把得到的值传出去
//另,放委派的东西本身也把她当参数放,所以要执行
//GetValue()才能得到方法
}
public override ACT<Tout> Get副本()
{
return new ActOrVal<Tin1, Tout>(
this.执行参数.Get副本(), this.执行式2.Get副本());
}
}
简单来说,他可以把委派跟参数吃进去
要用的时候才去执行他
另外,参数本身也可以当作另一个执行式的传回值,在转型时就会执行GetValue()
到这边也还没有问题.................
=======================================================================
但是,当我想写个计数器时就出现问题了
public class 计数器 : ACT<bool>
{
int this.iCount;
ACT iWhenEnd;
//这是ACT<Tout>的基底类别,可以直接执行。
//不用管传回质的问题
public int GetI()
{
return this.iCount;
//设计给树的末端(ACT<int>)吃的,因为希望做出回圈的效果
}
public override bool GetValue()
{
总而言之,这段相当於
for(int iCount = 0;iCount<iEndValve;iCount+iadd)
在回圈内就传回true
bool RV;
this.iCount += this.iadd;
switch (this.条件)
{
case 条件式.无限回圈:
RV = true;
case 条件式.正数:
RV = this.iCount < this.iEndValve;
case 条件式.倒数:
RV = this.iCount > this.iEndValve;
}
if (!this.iLastBool) this.iWhenEnd.RunAction();
//没传回值的版本是: void RunAction()
//有传回值的,多一个: Tout GetValue()
//有传回值的(例如ACT<Tout>)可以转型为ACT
return RV;
}
public override ACT<bool> Get副本()
{
return (this.iWhenEnd != null) ?
new 计数器(this.iStart,
this.iEndValve, this.iadd,
this.iWhenEnd.Get副本())
:
new 计数器(this.iStart,
this.iEndValve, this.iadd);
}
}
=====================================================================
到这边.............
我发现我的树不是长这样
http://ppt.cc/@SRy
而是有可能会长这样......
http://ppt.cc/Sz96
因为可能有别的多个节点会拿计数器的.iCount()来用
ACT<Tout>里面放的可能是树中的方法,例如.iCount()
同理,之後打算要写的if....else、while、do...while区块
都可能会将「树」变成一张「网」
如果只是执行GetValue()或RunAction()的话还好
只看参数或是Mthod的话,那个还是「树」
在执行上不会有问题.....
但是..... 取得复本的话怎麽办?
public sealed class ActOrVal<Tout> : ACT<Tout>
{
public override ACT<Tout> Get副本()
{
if (this.执行式 == null) return new ActOrVal<Tout>(this.数值);
return new ActOrVal<Tout>(this.执行式);
}
}
↑这个的取得复本只会指向「旧的」计时器.GetI()
http://ppt.cc/aDR1
如果因为一个.GetI()而建立一个新的计数器
就会变成这样
http://ppt.cc/-p@o
因此,在用递回复制复本的时候,要想办法将不同复本都指向正确的目标
请问有办法让所有复本都指向新的计数器吗?
==========================================================================
题目有些复杂,先谢谢你花时间看这个问题。
--
20330
6/17 - □ (本文已被吃掉)
干!这梗有毒...救命~~
20331
6/17 - □ (本文已被吃掉)
〒 〒 ◤
20332
1 6/17 - □ (本文已被吃掉)
▼▼▼▼
20333
XX 6/17 - 囧 (哈哈拎北有毒)
\▲▲▲▲\ =
●20334
1 6/17 - □ (本文已被吃掉)
20335 6/17 - □ (本文已被吃掉)
口卡口卡尝百草
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 163.27.109.101
※ 编辑: SDNiceBoat 来自: 163.27.109.101 (08/23 23:05)
※ 编辑: SDNiceBoat 来自: 163.27.109.101 (08/23 23:08)
※ 编辑: SDNiceBoat 来自: 163.27.109.101 (08/23 23:40)
※ 编辑: SDNiceBoat 来自: 163.27.109.101 (08/23 23:41)
1F:→ SDNiceBoat:请问一下1...... 有人看得懂题目吗? = = 08/25 14:14
2F:推 popmentos:完全看不懂 @_@ 08/25 21:30
3F:→ SDNiceBoat:orz.... 我努力试着让他白话一点...... 08/25 21:39
4F:推 popmentos:感恩 08/25 21:49
5F:推 tf1515:是说要让Act<bool>和Act<int>都指向新的计数器吗? 08/26 13:59
6F:→ SDNiceBoat:没错 08/26 14:50
7F:→ SDNiceBoat:可是这里有个问题,那实际上是指向该物件的「方法」, 08/26 14:50
8F:→ SDNiceBoat:而不是该物件。 08/26 14:51
9F:→ SDNiceBoat:目前是做了个ACT2<Tout>介面,让ACT<Tout>可以指向 08/26 14:52
10F:→ SDNiceBoat:ACT2<Tout>物件..... 虽然勉强可以解决,但还是有缺点 08/26 14:53
11F:→ SDNiceBoat:那就是.... 不能自动转型,自己定义的运算子不能用到介 08/26 14:53
12F:→ SDNiceBoat:面,例如:ACT2<Tout> → ACT<Tout> 要手动转。 08/26 14:54
13F:→ SDNiceBoat:另一个缺点是..... 一种型别只能有一个输出值。我没办 08/26 14:55
14F:→ SDNiceBoat:法让一个物件同时输出两个int值之类的 08/26 14:56
15F:→ SDNiceBoat:说错了,ACT2<Tout> → ACT<Tout>不是要手动转,是根本 08/26 14:57
16F:→ SDNiceBoat:没办法转,要用new ACT<Tout>(ACT2<Tout>) 这样 08/26 14:58