ExpressionEvaluator.cs类文件(程序写的很好, 好在不需要注释就能看懂。)
中缀转后缀
表达式字符串的处理符号解析
表达式字符串的处理符号事实fact解析
操作符号,函数解析
对应的操作符号,函数 的处理方法
public class ExpressionEvaluator { public event RuleEngine.EvidenceLookupHandler GetEvidence;//证明查找事件 /// <summary> /// 相关证明 /// </summary> /// <param name="symbols"></param> /// <returns></returns> public static string[] RelatedEvidence(List<Symbol> symbols) { ArrayList al = new ArrayList(); foreach (Symbol symbol in symbols) { if (symbol.type != Type.Fact) continue; al.Add(symbol.name); } return (string[])al.ToArray(typeof(string)); } #region 求值 //逻辑正则式 private static readonly string LogicalRegEx = @"(\x29|\x28|>=|<=|!=|==|<|>|AND|OR|NOT|ISNULL|XOR|\x2b|\x2d|\x2a|\x2f)"; protected double result = 0; protected List<Symbol> infix = new List<Symbol>();//中缀 protected List<Symbol> postfix = new List<Symbol>();//后缀 public enum Type { Fact, Value, Operator, Function, Result, OpenBracket, CloseBracket, Invalid } public struct Symbol// 象征;符号;标志 { public string name; public IEvidenceValue value; public Type type; public override string ToString() { return name; } } public ExpressionEvaluator() { } /// <summary> /// 中缀 /// </summary> public List<Symbol> Infix { get { return new List<Symbol>(infix); } set { infix = value; } } /// <summary> /// 后缀 /// </summary> public List<Symbol> Postfix { get { return new List<Symbol>(postfix); } set { postfix = value; } } /// <summary> /// 中缀表达式转换成 infix /// </summary> /// <param name="eq">方程式,等式equation</param> public void Parse(string eq) { Debug.Write("中缀表达式转换: " + eq + " : "); //清空 infix.Clear(); postfix.Clear(); //tokinize string Regex regex = new Regex(LogicalRegEx); string[] rawTokins = regex.Split(eq);//中缀表达式切割 for (int x = 0; x < rawTokins.Length; x++) { string currentTokin = rawTokins[x].Trim(); if (currentTokin == null || currentTokin == String.Empty) continue; //空格跳过 Symbol current = ParseToSymbol(currentTokin); //中缀加入Symbol infix.Add(current); Debug.Write(current.name + "|"); } Trace.WriteLine(""); } /// <summary> /// 字符串转换成Symbol /// </summary> /// <param name="s"></param> /// <returns></returns> /// <remarks>表达式字符串的处理符号解析</remarks> private Symbol ParseToSymbol(string s) { Symbol sym = new Symbol(); if (IsOpenParanthesis(s)) { sym.name = s; sym.type = Type.OpenBracket; } else if (IsCloseParanthesis(s)) { sym.name = s; sym.type = Type.CloseBracket; } else if (IsFunction(s)) //isfunction must come b4 isvariable because its an exact match where the other isnt { sym.name = s; sym.type = Type.Function; } else if (IsOperator(s)) { sym.name = s; sym.type = Type.Operator; } else if (IsBoolean(s)) { Naked naked = new Naked(Boolean.Parse(s), typeof(bool)); sym.name = s; sym.value = naked; sym.type = Type.Value; } else if (IsFact(s)) { sym.name = s; sym.type = Type.Fact; } else if (IsNumber(s)) { Naked naked = new Naked(Double.Parse(s), typeof(double)); sym.name = s; sym.value = naked; sym.type = Type.Value; } else if (IsString(s)) { Naked naked = new Naked(s.Substring(1, s.Length - 2), typeof(string)); sym.name = s; sym.value = naked; sym.type = Type.Value; } else { //who knows what it is so throw an exception throw new Exception("Invalid tokin: " + s); } return sym; } //是否是事实 private bool IsFact(string s) { if (s == null) return false; //变量必须第一位为字母,其余为数字和字母 bool result = true; if (!Char.IsLetter(s[0])) { result = false; return result; } foreach (char c in s.ToCharArray()) { if (Char.IsLetter(c) || Char.IsNumber(c)) continue; result = false; break; } return result; } //是否是布尔 private bool IsBoolean(string s) { if (s != null && (s.ToLower() == "true" || s.ToLower() == "false")) return true; else return false; } //是否是数字 private bool IsNumber(string s) { if (s == null) return false; bool result = true; foreach (char c in s.ToCharArray()) { if (Char.IsNumber(c)) continue; result = false; break; } return result; } //是否是字符串 private bool IsString(string s) { if (s == null) return false; bool result = false; if (s.StartsWith(@"""") && s.EndsWith(@"""")) result = true; return result; } //是否是打开的小括号 private bool IsOpenParanthesis(string s) { if (s == null) return false; // bool result = false; if (s == "(") result = true; return result; } //是否是关闭的小括号 private bool IsCloseParanthesis(string s) { if (s == null) return false; // bool result = false; if (s == ")") result = true; return result; } //是否是操作符号 private bool IsOperator(string s) { if (s == null) return false; bool result = false; switch (s) { case "+": case "-": case "/": case "*": case "^": case "==": case "!=": case ">=": case "<=": case ">": case "<": case "AND": case "OR": case "NOT": case "XOR": result = true; break; } return result; } //是否是函数 private bool IsFunction(string s) { if (s == null) return false; bool result = false; switch (s) { case "ISNULL": result = true; break; } return result; } #endregion #region 中缀转换成后缀 public void InfixToPostfix() { Debug.Write("中缀转换成后缀: "); postfix.Clear(); Stack postfixStack = new Stack();//栈 foreach (Symbol s in infix) { if (s.type == Type.Value || s.type == Type.Fact) { Debug.Write(s.name + "|"); postfix.Add(s);//事实加入后缀中 } else if (s.type == Type.Operator || s.type == Type.Function) { //操作符或者函数 while (postfixStack.Count > 0 && !DeterminePrecidence(s, (Symbol)postfixStack.Peek())) { Debug.Write(((Symbol)postfixStack.Peek()).name + "|"); postfix.Add((Symbol)postfixStack.Pop());//把后缀栈中的弹出到List中; } //压入后缀栈 postfixStack.Push(s); } else if (s.type == Type.OpenBracket)//开括号 { postfixStack.Push(s); //压入后缀栈 } else if (s.type == Type.CloseBracket)//关括号 { //pop off stack to '(', discard '('. while (((Symbol)postfixStack.Peek()).type != Type.OpenBracket) { Debug.Write(((Symbol)postfixStack.Peek()).name + "|"); postfix.Add((Symbol)postfixStack.Pop());//把后缀栈中的弹出到List中; } postfixStack.Pop(); //discard '(' 在后缀栈中弹出 } else { throw new Exception("非法 符号: " + s.name); } } //now we pop off whats left on the stack while (postfixStack.Count > 0) { Debug.Write(((Symbol)postfixStack.Peek()).name + "|"); postfix.Add((Symbol)postfixStack.Pop());//把后缀栈中的弹出到List中; } Trace.WriteLine(""); } //操作符优先级 private bool DeterminePrecidence(Symbol higher, Symbol lower) { int s1 = Precidence(higher); int s2 = Precidence(lower); if (s1 > s2) return true; else return false; } private int Precidence(Symbol s) { int result = 0; switch (s.name) { case "*": case "/": case "%": result = 32; break; case "+": case "-": result = 16; break; case ">": case "<": case ">=": case "<=": result = 8; break; case "==": case "!=": result = 4; break; case "NOT": result = 3; break; case "AND": result = 2; break; case "XOR": case "OR": result = 1; break; } //函数具有最高的优先级 if (s.type == Type.Function) result = 64; return result; } #endregion /// <summary> /// 计算 /// </summary> /// <returns></returns> public Symbol Evaluate() { Stack operandStack = new Stack();//操作符号栈 foreach (Symbol s in postfix) { if (s.type == Type.Value) { operandStack.Push(s); } else if (s.type == Type.Operator) { Symbol op3 = new Symbol(); //result Symbol op1; Symbol op2; switch (s.name) { //操作要求两个参数-- 执行操作方法。 case "+": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateAddition(op1, op2); break; case "-": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateSubtraction(op1, op2); break; case "*": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateMultiplication(op1, op2); break; case "/": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateDivision(op1, op2); break; case "==": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateEquals(op1, op2); break; case "!=": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateNEquals(op1, op2); break; case ">": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateGreaterThan(op1, op2); break; case "<": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateLessThan(op1, op2); break; case ">=": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateGreaterThanEqual(op1, op2); break; case "<=": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateLessThanEqual(op1, op2); break; case "AND": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateAnd(op1, op2); break; case "OR": op2 = (Symbol)operandStack.Pop(); op1 = (Symbol)operandStack.Pop(); op3 = EvaluateOr(op1, op2); break; case "NOT": op1 = (Symbol)operandStack.Pop(); //一个参数 op3 = EvaluateNot(op1); break; default: throw new Exception(String.Format("Invalid operator: {0} of type", s.name, s.type)); } operandStack.Push(op3);//压入加过 } else if (s.type == Type.Function)//函数 { //Symbol[] parameters; Symbol op3 = new Symbol(); op3.type = Type.Value; //IEvidence fact; switch (s.name) { case "ISNULL": Symbol symbol = (Symbol)operandStack.Pop(); op3.value = new Naked(false, typeof(bool)); if (symbol.type == Type.Invalid || symbol.value.Value == null) { op3.value = new Naked(true, typeof(bool)); } operandStack.Push(op3); Trace.WriteLine(String.Format("ExpressionEvaluator ISNULL {0} = {1}", symbol.name, op3.value.Value)); break; default: throw new Exception(String.Format("Invalid function: {0} of type {1}", s.name, s.type)); } } else if (s.type == Type.Fact)//事实 { Symbol op3 = new Symbol(); op3.type = Type.Value; IEvidence fact; fact = GetEvidence(this, new EvidenceLookupArgs(s.name));//得到证明 op3.value = new Naked(fact.Value, fact.ValueType); operandStack.Push(op3); Trace.WriteLine(String.Format("ExpressionEvaluator FACT {0} = {1}", fact.ID, fact.Value)); continue; } else { throw new Exception(String.Format("Invalid symbol type: {0} of type {1}", s.name, s.type)); } } Symbol returnValue = (Symbol)operandStack.Pop(); if (operandStack.Count > 0) throw new Exception("Invalid equation? OperandStack should have a count of zero."); return returnValue; } #region 计算 /// <summary> /// 加法 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateAddition(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; object o1 = null; object o2 = null; object replacement; try { o1 = op1.value.Value; o2 = op2.value.Value; if (o1 is string || o2 is string) replacement = o1.ToString() + o2.ToString(); else if (o1 is double && o2 is double) replacement = (double)o1 + (double)o2; else throw new Exception("only to be caught"); } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} + {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> ///减法 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateSubtraction(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; object o1 = null; object o2 = null; object replacement; try { o1 = op1.value.Value; o2 = op2.value.Value; if (o1 is string || o2 is string) throw new Exception("Cant subtract strings."); else if (o1 is double && o2 is double) replacement = (double)o1 - (double)o2; else throw new Exception("only to be caught"); } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} - {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> ///乘法 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateMultiplication(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; object o1 = null; object o2 = null; object replacement; try { o1 = op1.value.Value; o2 = op2.value.Value; if (o1 is string || o2 is string) throw new Exception("cant multiple strings"); else if (o1 is double && o2 is double) replacement = (double)o1 * (double)o2; else throw new Exception("only to be caught"); } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} * {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> ///除法 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateDivision(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; object o1 = null; object o2 = null; object replacement; try { o1 = op1.value.Value; o2 = op2.value.Value; if (o1 is string || o2 is string) throw new Exception("Cant divide strings"); else if (o1 is double && o2 is double) replacement = (double)o1 / (double)o2; else throw new Exception("only to be caught"); } catch { replacement = false; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} / {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 相等 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateEquals(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; object o1 = null; object o2 = null; object replacement; try { o1 = op1.value.Value; o2 = op2.value.Value; bool result = o1.Equals(o2); replacement = result; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} == {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 不等 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateNEquals(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; object o1 = null; object o2 = null; object replacement; try { o1 = op1.value.Value; o2 = op2.value.Value; bool result = !(o1.Equals(o2)); replacement = result; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} != {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 逻辑与 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateAnd(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; bool b1 = false; bool b2 = false; //see if the facts are not equal object replacement; try { b1 = (bool)op1.value.Value; b2 = (bool)op2.value.Value; replacement = (b1 && b2); } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} AND {1} = {2}", b1, b2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 逻辑非 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateNot(Symbol op1) { Symbol op3 = new Symbol(); op3.type = Type.Value; bool b1 = false; //see if the facts are not equal object replacement; try { b1 = (bool)op1.value.Value; replacement = (!b1); } catch //FUTURE: only catch specific errors and throw others up the stack { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator NOT {0} = {1}", b1, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 逻辑或 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateOr(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; bool b1 = false; bool b2 = false; //see if the facts are not equal object replacement; try { try { b1 = (bool)op1.value.Value; } catch { } try { b2 = (bool)op2.value.Value; } catch { } replacement = b1 || b2; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} OR {1} = {2}", b1, b2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 大于 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateGreaterThan(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; IComparable o1 = null; IComparable o2 = null; //see if the facts are not equal object replacement; try { o1 = (IComparable)op1.value.Value; o2 = (IComparable)op2.value.Value; int result; result = o1.CompareTo(o2); if (result == 1) replacement = true; else replacement = false; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} > {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 小于 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateLessThan(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; IComparable o1 = null; IComparable o2 = null; //see if the facts are not equal object replacement; try { o1 = (IComparable)op1.value.Value; o2 = (IComparable)op2.value.Value; int result; result = o1.CompareTo(o2); if (result == -1) replacement = true; else replacement = false; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionExaluator {0} < {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 大于等于 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateGreaterThanEqual(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; IComparable o1 = null; IComparable o2 = null; //see if the facts are not equal object replacement; try { o1 = (IComparable)op1.value.Value; o2 = (IComparable)op2.value.Value; int result; result = o1.CompareTo(o2); if (result == 1 || result == 0) replacement = true; else replacement = false; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionEvaluator {0} >= {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } /// <summary> /// 小于等于 /// </summary> /// <param name="op1"></param> /// <param name="op2"></param> /// <returns></returns> private Symbol EvaluateLessThanEqual(Symbol op1, Symbol op2) { Symbol op3 = new Symbol(); op3.type = Type.Value; IComparable o1 = null; IComparable o2 = null; //see if the facts are not equal object replacement; try { o1 = (IComparable)op1.value.Value; o2 = (IComparable)op2.value.Value; int result; result = o1.CompareTo(o2); if (result == -1 || result == 0) replacement = true; else replacement = false; } catch { op3.type = Type.Invalid; op3.value = null; replacement = op3; } Trace.WriteLine(String.Format("ExpressionExaluator {0} <= {1} = {2}", o1, o2, replacement)); op3.value = new Naked(replacement, typeof(bool)); return op3; } #endregion |
声明事件, 用于得到证明(事实的值)。
配置RelatedEvidence 把所有的属于Fact的对象放入 ArrayList中。
定义正则表达式 匹配字符串(操作符,函数,括号等内容)。
枚举类型。
事实,fact ,
值 Value
,操作 Operator
,函数 Function
,结果 Result
做方括号 OpenBracket,
右方括号 CloseBracket,
无效的 Invalid
符号结构。 Symbol
name 名称
IEvidenceValue value 对象值
Type type Type类型
中缀表达式 Infix, 是一个 LIST(Symbol)
后缀表达式 PostFIx ,也是一个List(Symbol)
中缀转后缀
Parse(方程式)
按照正则的符号进行切割, 得到数组。一部分是符号,一部分是内容。
然后把数组内容转换成 Symbol 执行ParseToSymbol
是否是打开的括号,是则为 Type.OpenBracket 为括号时, Symbol没有值。
是否为关闭的括号。
是否为函数。 ISNULL, 和type.FUNCITON ,sYMBOL没有值。
是否为操作符, 把NOT 也看成操作符号。 本质上是! Type.Operator;sYMBOL没有值。
是否为布尔值
创建NAKED对象, 其值Symbolvalue是Naked对象。 Type.value
是否为事实。
当前的事实就是下面定义的字符和数字的组合的事实名称,
而我这里。 告警,监控点,监控点告警都是事实类型。
是否存在是函数。
事实不设置Symbol的值。 只设置name 和 类型 type.Fact
因为这里的事实都是以名字在XML文件中命名,然后再根据名字去调用得到值即可。
所以只存名字和类型了。
数字,字符串,布尔值都是Naked (基础数据类型,无包装)
其类型都是 type。Value。 其value 都是一个naked对象。
是否为数字
是否为字符串。
把 Symbol组成LIST, 加入到中缀LIST中去。
中缀转后缀
建立栈。
如果是value 或者fact, 存入后缀。
如果是符号或者函数,则
当栈中有值且, 匹配当前的类型与栈中最顶(不弹出)的类型 对优先级匹配。
如果当前优先级比栈顶的高则返回true。
低则返回false。 把栈顶的这个弹出,加入到后缀表达式。
上面操作不论真假,都把当前的压入栈。
如果类型是开括号,压入栈。
如果是关括号。 则判断栈顶是否是开括号, 不是开括号。则把栈顶弹出,加入后缀。
)压入栈。
最后把栈的内容都弹出输出。
例子:
如果有函数 ISNULL(Fact(F2))
中缀 ISNULL ( fACT ( f2))
然后中缀转后缀。
录入内容 | 后缀 | 栈 |
ISNULL |
| ISNULL |
( |
| ISNULL,( |
fACT | fACT | ISNULL,( |
( | fACT | ISNULL,(,( |
F2 | FACT,F2 | ISNULL,(,( |
) | FACT,F2 | ISNULL,( |
) | FACT,F2 | ISNULL |
录入完成,读栈 | FACT,F2,ISNULL | 空 |
|
|
|
FACT,F2,ISNULL
注意,注意,上面 出错,因为 不需要写FACT关键字, NOT(F2>F1)
直接写F1.F2即可认为
也就是说 最终结果是F2,ISNULL
下面是计算:
建立栈,如果是值,直接压入栈,
如果是操作符号。则 对栈中的前两个进行计算。
不同的类型,不同的方法。
计算后的值,存入栈中中。
如果是函数。
则 建立一个值类型的naked对象, 得到栈顶值Symbol对象,Symbol对象类型的值为空,则设置为 新naked对象的值为true。 否则为false。 为空(事实,函数,括号)。
压入栈
如果是事实。
则 得到事实,得到事实的值压入。
F2,ISNULL
1.Fact 事实
得到事实的值。 压入栈。
栈中有F2的值。
2.ISNULL 是函数。
计算栈顶的F2的值, 判断F2的值 不等于Invalid,不等于null
压入false。
则F2的值不等于空。
本人声明:沐海(http://my.oschina.net/mahaisong) 以上文章是经过本人设计实践和阅读其他文档得出。如果需要探讨或指教可以留言!欢迎