/// <summary>helper for applyMethExpr() + constExpr()</summary>
 public static MdaApplyMethodExpr indexedExpr(MdaExpr thisExpr, MdaMethod meth, object indexParam)
 {
     return new MdaApplyMethodExpr(thisExpr, meth, new MdaExpr[] { constExpr(indexParam) });
 }
 public static MdaSubExpr subExpr(MdaExpr parentExpr, MdaExpr subExpr)
 {
     return new MdaSubExpr(parentExpr, subExpr);
 }
 /// <summary>helper for applyMethExpr</summary>
 public static MdaApplyMethodExpr applyMethExpr2(MdaExpr thisExpr, MdaMethod meth, MdaExpr param0Expr, MdaExpr param1Expr)
 {
     return new MdaApplyMethodExpr(thisExpr, meth, new MdaExpr[] { param0Expr, param1Expr });
 }
 public static MdaApplyMethodExpr applyMethExpr(MdaExpr thisExpr, MdaMethod meth, MdaExpr[] paramsExpr)
 {
     return new MdaApplyMethodExpr(thisExpr, meth, paramsExpr);
 }
 public MdaSubExpr(MdaExpr parentExpr, MdaExpr subExpr)
 {
     this.parentExpr = parentExpr;
     this.subExpr = subExpr;
 }
        public MdaApplyMethodExpr(MdaExpr thisExpr, MdaMethod
			 method, MdaExpr[] paramsExpr)
        {
            this.thisExpr = thisExpr;
            this.method = method;
            this.paramsExpr = paramsExpr;
        }
        public bool TryParse(MdaClass objectType, 
		                            string exprText, out MdaExpr expr)
        {
            expr = null;
            if (exprText == null || exprText == string.Empty) return false;
            int indexFirstDot = exprText.IndexOf('.');
            if (indexFirstDot == -1)
            {
                Match match;

                if ((match = REGEX_simpleProp.Match(exprText)).Success)
                {
                    string propName = match.Groups[1].Value;
                    MdaField prop = objectType.findField(propName);
                    if (prop == null)
                    {
                        return false;
                    }
                    expr = MdaExprUtil.propExpr(prop);
                    return true;
                }
                else if (exprText.StartsWith("id()"))
                {
                    expr = MdaExprUtil.identityExpr();
                    return true;
                }
                else if (exprText.StartsWith("const("))
                {
                    int indexRightParent = exprText.IndexOf(")");
                    string constValText = exprText.Substring("const(".Length, indexRightParent-1);
                    object value;
                    if (!TryParseLitteralValue(constValText, out value))
                    {
                        expr = null;
                        return false;
                    }
                    expr = MdaExprUtil.constExpr(value);
                    return true;
                }
                else if (exprText.StartsWith("meth:"))
                {
                    int indexLeftParent = exprText.IndexOf("(");
                    int indexRightParent = exprText.IndexOf(")");
                    string methodName = exprText.Substring("meth:".Length, indexLeftParent-1);
                    string paramsText = exprText.Substring(indexLeftParent, indexRightParent-1);
                    // TODO NOT IMPLEMENTED YET ... parse params expr + thisExpr?? ...
                    // expr = MdaExprUtill.applyMethExpr(null, );
                    expr = null;
                    return false;
                }
                else if (exprText.StartsWith("formula("))
                {
                    // TODO NOT IMPLEMENTED YET ... parse ...
                    // expr = MdaExprUtill.formulaExpr(type, expr, declaredResultType);
                    expr = null;
                    return false;
                }
                else if ((match = REGEX_arrayIndex.Match(exprText)).Success)
                {
                    string propName = match.Groups[1].Value;
                    string indexValueText = match.Groups[2].Value;

                    MdaField prop = objectType.findField(propName);
                    if (prop == null)
                    {
                        return false;
                    }
                    object indexValueObj;
                    if (!TryParseLitteralValue(indexValueText, out indexValueObj))
                    {
                        return false;
                    }

                    // TODO NOT IMPLEMENTED YET ...
                    // expr = MdaExprUtill.indexedExpr(...);
                    return false;
                }
                else
                {
                    // unrecognized expr type!
                    return false;
                }

            }
            else
            {
                // sub expr "leftExpr.rightExpr" => recurse
                string leftPart = exprText.Substring(0, indexFirstDot);
                string rightPart = exprText.Substring(indexFirstDot+1, exprText.Length-indexFirstDot-1);
                MdaExpr leftExpr;
                // *** recurse leftExpr ***
                if (!TryParse(objectType, leftPart, out leftExpr)) {
                    return false;
                }
                MdaClass leftExprType = leftExpr.GetReturnMdaType();
                MdaExpr rightExpr;
                // *** recurse rightExpr ***
                if (!TryParse(leftExprType, rightPart, out rightExpr)) {
                    return false;
                }
                expr = MdaExprUtil.subExpr(leftExpr, rightExpr);
                return true;
            }
        }