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); }
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); }