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); } } }
public opCodeConvert(tokenizer tokenizer, iEvalTypedValue param1, EvalType EvalType) { mParam1 = param1; mParam1.ValueChanged += mParam1_ValueChanged; switch (EvalType) { case EvalType.Boolean: { mValueDelegate = TBool; mEvalType = EvalType.Boolean; break; } case EvalType.Date: { mValueDelegate = TDate; mEvalType = EvalType.Date; break; } case EvalType.Number: { mValueDelegate = TNum; mEvalType = EvalType.Number; break; } case EvalType.String: { mValueDelegate = TStr; mEvalType = EvalType.String; break; } default: { tokenizer.RaiseError("Cannot convert " + param1.SystemType.Name + " to " + EvalType); break; } } }
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 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); }