public override void ProcessFunction(TextFunctionPipelineArgs pipeArgs)
        {
            var args = pipeArgs.Args;

            switch (pipeArgs.FunctionName)
            {
                case "querystring": // querystring("key"), querystring("key","defaultvalue")
                    if (args.Length > 1)
                        pipeArgs.HandledResult = GetQueryStringValue((string)args[0], (string)args[1]);
                    else
                        pipeArgs.HandledResult = GetQueryStringValue((string)args[0], null);
                    break;
                case "htmlencode": // htmlencode("<p>htmlstuff</p>")
                    pipeArgs.HandledResult = HttpUtility.HtmlEncode((string)args[0]);
                    break;
                case "htmldecode": // htmldecode("<p>htmlstuff</p>")
                    pipeArgs.HandledResult = HttpUtility.HtmlDecode((string)args[0]);
                    break;
                case "urlencode": // urlencode("<p>urlstuff</p>")
                    pipeArgs.HandledResult = HttpUtility.UrlEncode((string)args[0]);
                    break;
                case "urldecode": // urldecode("<p>urlstuff</p>")
                    pipeArgs.HandledResult = HttpUtility.UrlDecode((string)args[0]);
                    break;
            }
        }
        public override void ProcessFunction(TextFunctionPipelineArgs pipeArgs)
        {
            var args = pipeArgs.Args;

            switch (pipeArgs.FunctionName)
            {
                case "lookup":
                    pipeArgs.HandledResult = GetLookupValue((string)args[0], (string)args[1]);
                    break;
                case "lookupforeach": // lookupforeach("AGUID|AnotherGUID|3GUIDs|4thGuid","LookupItemFieldName","|","<br/>")
                    pipeArgs.HandledResult = LookupForEachValue((string)args[0], (string)args[1], (string)args[2], (string)args[3]);
                    break;
                case "wildcard":
                    pipeArgs.HandledResult = GetWildcardValue((int)args[0]);
                    break;
            }
        }
        public override void ProcessFunction(TextFunctionPipelineArgs pipeArgs)
        {
            var args = pipeArgs.Args;
            var fxHandlers = pipeArgs.CustomFunctionHandlers;
            var result = string.Empty;

            if ( fxHandlers != null && fxHandlers.Length > 0)
            {
                foreach (var fx in fxHandlers)
                {
                    if (fx.ProcessFunction(pipeArgs.FunctionName, args, ref result))
                    {
                        pipeArgs.HandledResult = result;
                        break;
                    }
                }
            }
        }
        public override void ProcessFunction(TextFunctionPipelineArgs pipeArgs)
        {
            var args = pipeArgs.Args;

            switch (pipeArgs.FunctionName)
            {
                case "trim":
                    pipeArgs.HandledResult = ((string)args[0]).Trim();
                    break;
                case "replace":
                    pipeArgs.HandledResult = ((string)args[0]).Replace((string)args[1], (string)args[2]);
                    break;
                case "formatdate":
                    pipeArgs.HandledResult = FormatDate((string)args[0], (string)args[1]);
                    break;
                case "now":
                    if (args.Length == 0)
                        pipeArgs.HandledResult = DateTime.Now.ToString();
                    else
                        pipeArgs.HandledResult = DateTime.Now.ToString((string)args[0]);
                    break;
                case "if":
                    if ((bool)args[0])
                        pipeArgs.HandledResult = (string)args[1];
                    else
                        pipeArgs.HandledResult = (string)args[2];
                    break;
                case "dateadd":
                    pipeArgs.HandledResult = DateAdd((string)args[0], (string)args[1]);
                    break;
                case "substring":
                    var source = (string)args[0];
                    var startIndex = (int)args[1];
                    if (args.Length == 2)
                        pipeArgs.HandledResult = source.Substring(startIndex);
                    else if (args.Length == 3)
                    {
                        var length = (int)args[2];
                        pipeArgs.HandledResult = source.Substring(startIndex, Math.Min(source.Length - startIndex, length));
                    }
                    break;
            }
        }
        private object ProcessNode(ParseTreeNode node, string fxName)
        {
            object result = null;

            switch (node.Term.Name)
            {
                case "function_expression":
                    fxName = node.ChildNodes[0].FindTokenAndGetText().TrimStart('@');
                    var fxParams = (List<object>)ProcessNode(node.ChildNodes[1], fxName);
                    var args = new TextFunctionPipelineArgs()
                    {
                        FunctionName = fxName,
                        Args = fxParams.ToArray(),
                        CustomFunctionHandlers = _fxCustomHandlers
                    };
                    if (_fxHandlerLookup.ContainsKey(fxName))
                    {
                        var fx = _fxHandlerLookup[fxName];
                        fx.ProcessFunction(args);
                    }
                    else
                    {
                        // Send to the ProcessTextFunction pipeline....
                        CorePipeline.Run("ProcessTextFunction", args);

                        // Save reference to the handling processor...
                        if (args.FunctionHandled && args.HandledBy != null)
                            _fxHandlerLookup.Add(fxName, args.HandledBy);
                    }
                    if (args.FunctionHandled)
                        result = args.Result;
                    else
                        result = "'@" + fxName + "' function is not recognized.";
                    break;

                case "argument_list_par":
                case "argument_list_opt":
                    if (node.ChildNodes.Count == 0)
                        return new List<object>();
                    else
                        result = ProcessNode(node.FirstChild, fxName);
                    break;

                case "argument_list":
                    var parameters = new List<object>();
                    foreach (var p in node.ChildNodes)
                    {
                        var pValue = ProcessNode(p, fxName);
                        if (pValue != null)
                            parameters.Add(pValue);
                    }
                    result = parameters;
                    break;

                case "bin_op_expression":
                    var b_operand1 = ProcessNode(node.ChildNodes[0], fxName);
                    var b_operand2 = ProcessNode(node.ChildNodes[2], fxName);
                    var b_op = node.ChildNodes[1].FindTokenAndGetText();
                    result = EvaluateOperation(b_operand1, b_op, b_operand2);
                    break;

                case "parenthesized_expression":
                    result = ProcessNode(node.ChildNodes[0], fxName);
                    break;

                case "unary_expression":
                    var u_op = node.FindTokenAndGetText();
                    var u_operand = ProcessNode(node.ChildNodes[1], fxName);
                    result = EvaluateUnaryOperation(u_op, u_operand);
                    break;

                case "StringLiteral":
                    // Remove the surrounding quotes (")
                    var s = node.FindTokenAndGetText();
                    s = ResolveExpressionVariables(s); // resolve embedded field variables
                    result = s.Length > 2 ? s.Substring(1, s.Length - 2) : string.Empty;
                    break;

                case "guid_variable":
                    result = _variables[node.FindTokenAndGetText()];
                    break;

                case "Number":
                    var n = node.FindTokenAndGetText();
                    if (n.Contains("."))
                        result = decimal.Parse(n);
                    else
                        result = int.Parse(n);
                    break;

                case "true":
                case "True":
                    result = true;
                    break;
                case "false":
                case "False":
                    result = false;
                    break;
                case "null":
                    result = null;
                    break;
                default:
                    throw new Exception(string.Format("Unhandled argument type: [{0}][{1}]", node.Term.Name, node.FindTokenAndGetText()));
            }

            return result;
        }