protected void SwapParams(ref opCode Param1, ref opCode Param2) { opCode swp = Param1; Param1 = Param2; Param2 = swp; }
public opCodeUnary(eTokenType tt, opCode param1) { mParam1 = param1; mParam1.ValueChanged += mParam1_ValueChanged; EvalType v1Type = mParam1.EvalType; switch (tt) { case eTokenType.operator_not: { if (v1Type == EvalType.Boolean) { mValueDelegate = BOOLEAN_NOT; mEvalType = EvalType.Boolean; } break; } case eTokenType.operator_minus: { if (v1Type == EvalType.Number) { mValueDelegate = NUM_CHGSIGN; mEvalType = EvalType.Number; } break; } } }
private void ParseDot(ref opCode ValueLeft) { do { switch (mTokenizer.type) { case eTokenType.dot: { mTokenizer.NextToken(); break; } case eTokenType.open_parenthesis: { break; } default: { return; } } ParseIdentifier(ref ValueLeft); }while (true); }
public opCode Parse(string str) { if (str == null) { str = string.Empty; } mTokenizer = new tokenizer(this, str); mTokenizer.NextToken(); opCode res = ParseExpr(null /* TODO Change to default(_) if this is not a reference type */, ePriority.none); if (mTokenizer.type == eTokenType.end_of_formula) { if (res == null) { res = new opCodeImmediate(EvalType.String, string.Empty); } return(res); } else { mTokenizer.RaiseUnexpectedToken(); } return(res); }
public opCodeGetArrayEntry(opCode array, IList <iEvalTypedValue> @params) { iEvalTypedValue[] newParams = new iEvalTypedValue[@params.Count - 1 + 1]; int[] newValues = new int[@params.Count - 1 + 1]; @params.CopyTo(newParams, 0); mArray = array; mArray.ValueChanged += mBaseVariable_ValueChanged; mParams = newParams; mValues = newValues; mResultSystemType = array.SystemType.GetElementType(); mResultEvalType = Globals.GetEvalType(mResultSystemType); }
protected internal void Convert(tokenizer tokenizer, ref opCode param1, EvalType EvalType) { if (param1.EvalType != EvalType) { if (param1.CanReturn(EvalType)) { param1 = new opCodeConvert(tokenizer, param1, EvalType); } else { tokenizer.RaiseError("Cannot convert " + param1.Name + " into " + EvalType); } } }
private bool EmitCallFunction(ref opCode valueLeft, string funcName, IList <iEvalTypedValue> parameters, eCallType CallType, bool ErrorIfNotFound) { opCode newOpcode = null; if (valueLeft == null) { object functions = null; foreach (var funcs in mEvaluator.mEnvironmentFunctionsList) { functions = funcs; while (functions != null) { newOpcode = GetLocalFunction(funcs, funcs.GetType(), funcName, parameters, CallType); if (newOpcode != null) { goto Foo; } if (funcs is iEvalFunctions) { functions = ((iEvalFunctions)funcs).InheritedFunctions(); } else { break; } } } } else { newOpcode = GetLocalFunction(valueLeft, valueLeft.SystemType, funcName, parameters, CallType); } Foo: if (newOpcode != null) { valueLeft = newOpcode; return(true); } else { if (ErrorIfNotFound) { mTokenizer.RaiseError("Variable or method " + funcName + " was not found"); } return(false); } }
public opCodeBinary(tokenizer tokenizer, opCode param1, eTokenType tt, opCode param2) { mParam1 = param1; mParam2 = param2; mParam1.ValueChanged += mParam1_ValueChanged; mParam2.ValueChanged += mParam2_ValueChanged; EvalType v1Type = mParam1.EvalType; EvalType v2Type = mParam2.EvalType; switch (tt) { case eTokenType.operator_plus: { if (v1Type == EvalType.Number & v2Type == EvalType.Number) { mValueDelegate = NUM_PLUS_NUM; mEvalType = EvalType.Number; } else if (v1Type == EvalType.Number & v2Type == EvalType.Date) { SwapParams(ref mParam1, ref mParam2); mValueDelegate = DATE_PLUS_NUM; mEvalType = EvalType.Date; } else if (v1Type == EvalType.Date & v2Type == EvalType.Number) { mValueDelegate = DATE_PLUS_NUM; mEvalType = EvalType.Date; } else if (mParam1.CanReturn(EvalType.String) & mParam2.CanReturn(EvalType.String)) { Convert(tokenizer, ref param1, EvalType.String); mValueDelegate = STR_CONCAT_STR; mEvalType = EvalType.String; } break; } case eTokenType.operator_minus: { if (v1Type == EvalType.Number & v2Type == EvalType.Number) { mValueDelegate = NUM_MINUS_NUM; mEvalType = EvalType.Number; } else if (v1Type == EvalType.Date & v2Type == EvalType.Number) { mValueDelegate = DATE_MINUS_NUM; mEvalType = EvalType.Date; } else if (v1Type == EvalType.Date & v2Type == EvalType.Date) { mValueDelegate = DATE_MINUS_DATE; mEvalType = EvalType.Number; } break; } case eTokenType.operator_mul: { if (v1Type == EvalType.Number & v2Type == EvalType.Number) { mValueDelegate = NUM_MUL_NUM; mEvalType = EvalType.Number; } break; } case eTokenType.operator_div: { if (v1Type == EvalType.Number & v2Type == EvalType.Number) { mValueDelegate = NUM_DIV_NUM; mEvalType = EvalType.Number; } break; } case eTokenType.operator_percent: { if (v1Type == EvalType.Number & v2Type == EvalType.Number) { mValueDelegate = NUM_PERCENT_NUM; mEvalType = EvalType.Number; } break; } case eTokenType.operator_and: case eTokenType.operator_or: { Convert(tokenizer, ref mParam1, EvalType.Boolean); Convert(tokenizer, ref mParam2, EvalType.Boolean); switch (tt) { case eTokenType.operator_or: { mValueDelegate = BOOL_OR_BOOL; mEvalType = EvalType.Boolean; break; } case eTokenType.operator_and: { mValueDelegate = BOOL_AND_BOOL; mEvalType = EvalType.Boolean; break; } } break; } } if (mValueDelegate == null) { tokenizer.RaiseError("Cannot apply the operator " + tt.ToString().Replace("operator_", "") + " on " + v1Type.ToString() + " and " + v2Type.ToString()); } }
private void ParseIdentifier(ref opCode ValueLeft) { // first check functions IList <iEvalTypedValue> parameters; // parameters... // Dim types As New ArrayList string func = mTokenizer.value.ToString(); mTokenizer.NextToken(); bool isBrackets = false; parameters = ParseParameters(ref isBrackets); if (parameters != null) { IList <iEvalTypedValue> EmptyParameters = new List <iEvalTypedValue>(); bool ParamsNotUsed = false; if (mEvaluator.Syntax == eParserSyntax.Vb) { // in vb we don't know if it is array or not as we have only parenthesis // so we try with parameters first if (!EmitCallFunction(ref ValueLeft, func, parameters, eCallType.all, false)) { // and if not found we try as array or default member EmitCallFunction(ref ValueLeft, func, EmptyParameters, eCallType.all, true); ParamsNotUsed = true; } } else if (isBrackets) { if (!EmitCallFunction(ref ValueLeft, func, parameters, eCallType.property, false)) { EmitCallFunction(ref ValueLeft, func, EmptyParameters, eCallType.all, true); ParamsNotUsed = true; } } else if (!EmitCallFunction(ref ValueLeft, func, parameters, eCallType.field | eCallType.method, ErrorIfNotFound: false)) { EmitCallFunction(ref ValueLeft, func, EmptyParameters, eCallType.all, ErrorIfNotFound: true); ParamsNotUsed = true; } // we found a function without parameters // so our parameters must be default property or an array Type t = ValueLeft.SystemType; if (ParamsNotUsed) { if (t.IsArray) { if (parameters.Count == t.GetArrayRank()) { ValueLeft = new opCodeGetArrayEntry(ValueLeft, parameters); } else { mTokenizer.RaiseError("This array has " + t.GetArrayRank() + " dimensions"); } } else { MemberInfo mi; mi = GetMemberInfo(t, null /* TODO Change to default(_) if this is not a reference type */, parameters); if (mi != null) { ValueLeft = opCodeCallMethod.GetNew(mTokenizer, ValueLeft, mi, parameters); } else { mTokenizer.RaiseError("Parameters not supported here"); } } } } else { EmitCallFunction(ref ValueLeft, func, parameters, eCallType.all, ErrorIfNotFound: true); } }
private opCode ParseExpr(opCode Acc, ePriority priority) { opCode ValueLeft = null, valueRight = null; do { switch (mTokenizer.type) { case eTokenType.operator_minus: { // unary minus operator mTokenizer.NextToken(); ValueLeft = ParseExpr(null /* TODO Change to default(_) if this is not a reference type */, ePriority.unaryminus); ValueLeft = new opCodeUnary(eTokenType.operator_minus, ValueLeft); goto Foo; break; } case eTokenType.operator_plus: { // unary minus operator mTokenizer.NextToken(); break; } case eTokenType.operator_not: { mTokenizer.NextToken(); ValueLeft = ParseExpr(null /* TODO Change to default(_) if this is not a reference type */, ePriority.not); ValueLeft = new opCodeUnary(eTokenType.operator_not, ValueLeft); goto Foo; break; } case eTokenType.value_identifier: { ParseIdentifier(ref ValueLeft); goto Foo; break; } case eTokenType.value_true: { ValueLeft = new opCodeImmediate(EvalType.Boolean, true); mTokenizer.NextToken(); goto Foo; break; } case eTokenType.value_false: { ValueLeft = new opCodeImmediate(EvalType.Boolean, false); mTokenizer.NextToken(); goto Foo; break; } case eTokenType.value_string: { ValueLeft = new opCodeImmediate(EvalType.String, mTokenizer.value.ToString()); mTokenizer.NextToken(); goto Foo; break; } case eTokenType.value_number: { try { ValueLeft = new opCodeImmediate(EvalType.Number, double.Parse(mTokenizer.value.ToString(), System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture)); } catch (Exception ex) { mTokenizer.RaiseError(string.Format("Invalid number {0}", mTokenizer.value.ToString())); } mTokenizer.NextToken(); goto Foo; break; } case eTokenType.value_date: { try { ValueLeft = new opCodeImmediate(EvalType.Date, mTokenizer.value.ToString()); } catch (Exception ex) { mTokenizer.RaiseError(string.Format("Invalid date {0}, it should be #DD/MM/YYYY hh:mm:ss#", mTokenizer.value.ToString())); } mTokenizer.NextToken(); goto Foo; break; } case eTokenType.open_parenthesis: { mTokenizer.NextToken(); ValueLeft = ParseExpr(null /* TODO Change to default(_) if this is not a reference type */, ePriority.none); if (mTokenizer.type == eTokenType.close_parenthesis) { // good we eat the end parenthesis and continue ... mTokenizer.NextToken(); goto Foo; } else { mTokenizer.RaiseUnexpectedToken("End parenthesis not found"); } break; } case eTokenType.operator_if: { // first check functions IList <iEvalTypedValue> parameters = new List <iEvalTypedValue>(); mTokenizer.NextToken(); bool p = false; parameters = ParseParameters(ref p); goto Foo; break; } default: { goto Foo; break; } } }while (true)// parameters... ; Foo: if (ValueLeft == null) { mTokenizer.RaiseUnexpectedToken("No Expression found"); } ParseDot(ref ValueLeft); do { eTokenType tt; tt = mTokenizer.type; switch (tt) { case eTokenType.end_of_formula: { // end of line return(ValueLeft); } case eTokenType.value_number: { mTokenizer.RaiseUnexpectedToken("Unexpected number without previous opterator"); break; } case eTokenType.operator_plus: { if (priority < ePriority.plusminus) { mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.plusminus); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } case eTokenType.operator_minus: { if (priority < ePriority.plusminus) { mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.plusminus); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } case eTokenType.operator_concat: { if (priority < ePriority.concat) { mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.concat); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } case eTokenType.operator_mul: case eTokenType.operator_div: { if (priority < ePriority.muldiv) { mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.muldiv); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } case eTokenType.operator_percent: { if (priority < ePriority.percent) { mTokenizer.NextToken(); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, Acc); } else { goto Foo1; } break; } case eTokenType.operator_or: { if (priority < ePriority.or) { mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.or); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } case eTokenType.operator_and: { if (priority < ePriority.and) { mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.and); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } case eTokenType.operator_ne: case eTokenType.operator_gt: case eTokenType.operator_ge: case eTokenType.operator_eq: case eTokenType.operator_le: case eTokenType.operator_lt: { if (priority < ePriority.equality) { tt = mTokenizer.type; mTokenizer.NextToken(); valueRight = ParseExpr(ValueLeft, ePriority.equality); ValueLeft = new opCodeBinary(mTokenizer, ValueLeft, tt, valueRight); } else { goto Foo1; } break; } default: { goto Foo1; break; } } }while (true); Foo1: return(ValueLeft); }