ScriptObject ParseOperate(CodeOperator operate) { TokenType type = operate.Operator; ScriptObject left = ResolveOperand(operate.Left); switch (type) { case TokenType.Plus: ScriptObject right = ResolveOperand(operate.Right); if (left is ScriptString || right is ScriptString) { return new ScriptString(m_script, left.ToString() + right.ToString()); } return left.Compute(type, right); case TokenType.Minus: case TokenType.Multiply: case TokenType.Divide: case TokenType.Modulo: case TokenType.InclusiveOr: case TokenType.Combine: case TokenType.XOR: case TokenType.Shr: case TokenType.Shi: return left.Compute(type, ResolveOperand(operate.Right)); case TokenType.And: if (!left.LogicOperation()) return m_script.False; return m_script.CreateBool(ResolveOperand(operate.Right).LogicOperation()); case TokenType.Or: if (left.LogicOperation()) return m_script.True; return m_script.CreateBool(ResolveOperand(operate.Right).LogicOperation()); case TokenType.Equal: return m_script.CreateBool(left.Equals(ResolveOperand(operate.Right))); case TokenType.NotEqual: return m_script.CreateBool(!left.Equals(ResolveOperand(operate.Right))); case TokenType.Greater: case TokenType.GreaterOrEqual: case TokenType.Less: case TokenType.LessOrEqual: return m_script.CreateBool(left.Compare(type, ResolveOperand(operate.Right))); default: throw new ExecutionException(m_script, "不支持的运算符 " + type); } }
//获取一个Object private CodeObject GetObject() { Stack<TempOperator> operateStack = new Stack<TempOperator>(); Stack<CodeObject> objectStack = new Stack<CodeObject>(); while (true) { objectStack.Push(GetOneObject()); if (!P_Operator(operateStack, objectStack)) break; } while (true) { if (operateStack.Count <= 0) break; TempOperator oper = operateStack.Pop(); CodeOperator binexp = new CodeOperator(objectStack.Pop(), objectStack.Pop(), oper.Operator, m_strBreviary, GetSourceLine()); objectStack.Push(binexp); } CodeObject ret = objectStack.Pop(); if (ret is CodeMember) { CodeMember member = ret as CodeMember; if (member.Calc == CALC.NONE) { Token token = ReadToken(); switch (token.Type) { case TokenType.Assign: case TokenType.AssignPlus: case TokenType.AssignMinus: case TokenType.AssignMultiply: case TokenType.AssignDivide: case TokenType.AssignModulo: case TokenType.AssignCombine: case TokenType.AssignInclusiveOr: case TokenType.AssignXOR: case TokenType.AssignShr: case TokenType.AssignShi: ret = new CodeAssign(member, GetObject(), token.Type, m_strBreviary, token.SourceLine); break; default: UndoToken(); break; } } } if (PeekToken ().Type == TokenType.QuestionMark) { ReadToken(); CodeTernary ternary = new CodeTernary(); ternary.Allow = ret; ternary.True = GetObject(); ReadColon(); ternary.False = GetObject(); return ternary; } return ret; }
//解析操作符 private bool P_Operator(Stack<TempOperator> operateStack, Stack<CodeObject> objectStack) { TempOperator curr = TempOperator.GetOper(PeekToken().Type); if (curr == null) return false; ReadToken(); while (operateStack.Count > 0) { TempOperator oper = operateStack.Peek(); if (oper.Level >= curr.Level) { operateStack.Pop(); CodeOperator binexp = new CodeOperator(objectStack.Pop(), objectStack.Pop(), oper.Operator, m_strBreviary, GetSourceLine()); objectStack.Push(binexp); } else { break; } } operateStack.Push(curr); return true; }
ScriptObject ParseOperate(CodeOperator operate) { TokenType type = operate.Operator; ScriptObject left = ResolveOperand(operate.Left); if (type == TokenType.Plus) { ScriptObject right = ResolveOperand(operate.Right); if (left is ScriptString || right is ScriptString) { return m_script.CreateString(left.ToString() + right.ToString()); } else if (left is ScriptNumber && right is ScriptNumber){ return (left as ScriptNumber).Compute(TokenType.Plus, right as ScriptNumber); } else { throw new ExecutionException(m_script, "operate [+] left right is not same type"); } } else if (type == TokenType.Minus || type == TokenType.Multiply || type == TokenType.Divide || type == TokenType.Modulo || type == TokenType.InclusiveOr || type == TokenType.Combine || type == TokenType.XOR || type == TokenType.Shr || type == TokenType.Shi) { ScriptNumber leftNumber = left as ScriptNumber; if (leftNumber == null) throw new ExecutionException(m_script, "运算符[左边]必须是number类型"); ScriptNumber rightNumber = ResolveOperand(operate.Right) as ScriptNumber; if (rightNumber == null) throw new ExecutionException(m_script, "运算符[右边]必须是number类型"); return leftNumber.Compute(type, rightNumber); } else { if (left is ScriptBoolean) { bool b1 = ((ScriptBoolean)left).Value; if (type == TokenType.And) { if (b1 == false) return m_script.False; ScriptBoolean right = ResolveOperand(operate.Right) as ScriptBoolean; if (right == null) throw new ExecutionException(m_script, "operate [&&] right is not a bool"); return right.Value ? m_script.True : m_script.False; } else if (type == TokenType.Or) { if (b1 == true) return m_script.True; ScriptBoolean right = ResolveOperand(operate.Right) as ScriptBoolean; if (right == null) throw new ExecutionException(m_script, "operate [||] right is not a bool"); return right.Value ? m_script.True : m_script.False; } else { if (type != TokenType.Equal && type != TokenType.NotEqual) throw new ExecutionException(m_script, "nonsupport operate [" + type + "] with bool"); ScriptBoolean right = ResolveOperand(operate.Right) as ScriptBoolean; if (right == null) return type == TokenType.Equal ? m_script.False : m_script.True; bool b2 = right.Value; if (type == TokenType.Equal) return b1 == b2 ? m_script.True : m_script.False; else return b1 != b2 ? m_script.True : m_script.False; } } else { ScriptObject right = ResolveOperand(operate.Right); if (left is ScriptNull || right is ScriptNull) { bool ret = false; if (type == TokenType.Equal) ret = (left == right); else if (type == TokenType.NotEqual) ret = (left != right); else throw new ExecutionException(m_script, "nonsupport operate [" + type + "] with null"); return ret ? m_script.True : m_script.False; } if (type == TokenType.Equal) { return left.ObjectValue.Equals(right.ObjectValue) ? m_script.True : m_script.False; } else if (type == TokenType.NotEqual) { return !left.ObjectValue.Equals(right.ObjectValue) ? m_script.True : m_script.False; } if (left.Type != right.Type) throw new ExecutionException(m_script, "[operate] left right is not same type"); if (left is ScriptString) { return ((ScriptString)left).Compare(type, (ScriptString)right) ? m_script.True : m_script.False; } else if (left is ScriptNumber) { return ((ScriptNumber)left).Compare(type, (ScriptNumber)right) ? m_script.True : m_script.False; } else { throw new ExecutionException(m_script, "nonsupport operate [" + type + "] with " + left.Type); } } } }