void Init()
        {
            this._functions = new Dictionary<string, TemplateFunction>(StringComparer.InvariantCultureIgnoreCase);

            this._variables = new VariableScope();

            _functions.Add("equals", new TemplateFunction(FuncEquals));
            _functions.Add("notequals", new TemplateFunction(FuncNotEquals));
            _functions.Add("iseven", new TemplateFunction(FuncIsEven));
            _functions.Add("isodd", new TemplateFunction(FuncIsOdd));
            _functions.Add("isempty", new TemplateFunction(FuncIsEmpty));
            _functions.Add("isnotempty", new TemplateFunction(FuncIsNotEmpty));
            _functions.Add("isnumber", new TemplateFunction(FuncIsNumber));
            _functions.Add("toupper", new TemplateFunction(FuncToUpper));
            _functions.Add("tolower", new TemplateFunction(FuncToLower));
            _functions.Add("isdefined", new TemplateFunction(FuncIsDefined));
            _functions.Add("ifdefined", new TemplateFunction(FuncIfDefined));
            _functions.Add("len", new TemplateFunction(FuncLen));
            _functions.Add("tolist", new TemplateFunction(FuncToList));
            _functions.Add("isnull", new TemplateFunction(FuncIsNull));
            _functions.Add("not", new TemplateFunction(FuncNot));
            _functions.Add("iif", new TemplateFunction(FuncIif));
            _functions.Add("format", new TemplateFunction(FuncFormat));
            _functions.Add("trim", new TemplateFunction(FuncTrim));
            _functions.Add("filter", new TemplateFunction(FuncFilter));
            _functions.Add("gt", new TemplateFunction(FuncGt));
            _functions.Add("lt", new TemplateFunction(FuncLt));
            _functions.Add("compare", new TemplateFunction(FuncCompare));
            _functions.Add("or", new TemplateFunction(FuncOr));
            _functions.Add("and", new TemplateFunction(FuncAnd));
            _functions.Add("comparenocase", new TemplateFunction(FuncCompareNoCase));
            _functions.Add("stripnewlines", new TemplateFunction(FuncStripNewLines));
        }
 public VariableScope(VariableScope parent)
 {
     this.parent = parent;
     this.values = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
 }
        protected void ProcessTemplate(string name, Tag tag)
        {
            Template useTemplate = _currentTemplate.FindTemplate(name);
            if (useTemplate == null)
            {
                string msg = string.Format("Template '{0}' not found", name);
                WriteError(msg, tag.Line, tag.Col);
                return;
            }

            // process inner elements and save content
            TextWriter saveWriter = _writer;
            _writer = new StringWriter();
            string content = string.Empty;

            try
            {
                ProcessElements(tag.InnerElements);

                content = _writer.ToString();
            }
            catch
            {
                return; // on error, do not do tag inclusion
            }
            finally
            {
                _writer = saveWriter;
            }

            Template saveTemplate = _currentTemplate;
            _variables = new VariableScope(_variables);
            _variables["innerText"] = content;

            try
            {
                foreach (TagAttribute attrib in tag.Attributes)
                {
                    object val = EvalExpression(attrib.Expression);
                    _variables[attrib.Name] = val;
                }

                _currentTemplate = useTemplate;
                ProcessElements(_currentTemplate.Elements);
            }
            finally
            {
                _variables = _variables.Parent;
                _currentTemplate = saveTemplate;
            }
        }