function cbCalculator(form)
{
    this.form = form;

    this.calculate = function(instruction)
    {
        var t = new Tokenizer();
        t.process(instruction);
        if (t.error != '')
        {
            alert(t.error);
            return;
        }



        //var d = '';
        //for (var i = 0; i < t.tokens.length; i++)
        //{
        //    d += t.tokens[i].getDescription() + ' ';
        //}
         


        var test = new TokenSyntaxTest(t.tokens);
        test.test();
        if (test.error!='')
        {
            alert(test.error);
            return;
        }


        var b = new TokenTreeBuilder(t.tokens);
        b.process();
        //alert(b.root.children[1].value.name);

        var node = b.getRoot();

        return this.pCalculate(node); 

    }


    this.pCalculate = function(node)
    {

        if (node.children.length==0)
        {
            if (node.type.name=='variable')
            {


                if (this.form == undefined || this.form == null)
                    var e = $('*[name='+node.value+']');
                else
                    var e = $('*[name='+node.value+']',this.form);
                
                if (e.attr('type')=='radio')
                {
                    if (this.form == undefined || this.form == null)
                        var r = $('*[name='+node.value+']:checked').val();
                    else
                        var r = $('*[name='+node.value+']:checked',this.form).val();
                }
                else if (e.attr('type')=='checkbox')
                {
                    if ($('*[name='+node.value+']:checked').length>0)
                        return 1;
                    else
                        return 0;
                }
                else
                {
                    if (e.attr('nodeName')=='INPUT')
                    {
                        if (e.isEmpty())
                        {
                            consoleLog('Found EMPTY value for variable ' + node.value);
                            return '';
                        }
                    }
                    var r = e.val();
                }
                consoleLog('Found value ' + r + ' for variable ' + node.value);

                return r;
                //return $('#'+node.value).val();
                //return eval(node.value);
            }

            consoleLog('Returning ' + node.value);
            return node.value;
        }

        if (node.type.name=='function')
        {
            //Math functions

            if (node.value=='abs')
            {
                var a = this.pCalculate(node.children[0]);
                return Math.abs(a);
            }
            else if (node.value=='acos')
            {
                var a = this.pCalculate(node.children[0]);
                return Math.acos(a);
            }
            else if (node.value=='ceil')
            {
                var a = this.pCalculate(node.children[0]);
                return Math.ceil(a);
            }
            else if (node.value=='floor')
            {
                var a = this.pCalculate(node.children[0]);
                return Math.floor(a);
            }
            else if (node.value=='parseint')
            {
                var a = this.pCalculate(node.children[0]);
                return parseInt(a, 10);
            }
            else if (node.value=='round')
            {
                var a = this.pCalculate(node.children[0]);
                return Math.round(a);

            }
            else if (node.value=='max')
            {
                var a = this.pCalculate(node.children[0]);
                var b = this.pCalculate(node.children[1]);
                return Math.max(a, b);
            }
            else if (node.value=='min')
            {
                var a = this.pCalculate(node.children[0]);
                var b = this.pCalculate(node.children[1]);
                return Math.min(a, b);
            }
            else if (node.value=='pow')
            {
                var z = this.pCalculate(node.children[0]);
                var a = this.pCalculate(node.children[1]);
                return Math.pow(z,a);
            }
            else if (node.value=='sqr')
            {
                var v = this.pCalculate(node.children[0]);
                return v * v;
            }



            //String functions
            else if (node.value=='length')
            {
                var a = this.pCalculate(node.children[0]);
                return a.length;

            }
            else if (node.value=='substring')
            {
                var s = this.pCalculate(node.children[0]);
                var p = this.pCalculate(node.children[1]);
                if (node.children.length==2)
                {
                    return s.substring(p);
                }
                else
                {
                    var l = this.pCalculate(node.children[2]);
                    return s.substring(p,parseInt(s,10) + parseInt(l,10));
                }
            }
            else if (node.value=='uppercase')
            {
                var s = this.pCalculate(node.children[0]);
                return s.toUpperCase();
            }
            else if (node.value=='lowercase')
            {
                var s = this.pCalculate(node.children[0]);
                return s.toLowerCase();
            }
            else if (node.value=='indexof')
            {
                //string.indexOf(searchstring, start)
                var s = this.pCalculate(node.children[0]);
                var n = this.pCalculate(node.children[1]);
                if (node.children.length==2)
                {
                    return s.indexOf(n);
                }
                else
                {
                    var p = this.pCalculate(node.children[2]);
                    return s.indexOf(n,p);
                }
            }
            else if (node.value=='replace')
            {
                var s = this.pCalculate(node.children[0]);
                var n = this.pCalculate(node.children[1]);
                var r = this.pCalculate(node.children[2]);

                var expression = new RegExp(n,'g');

                return s.replace(expression, r);
            }
            else if (node.value=='startswith')
            {
                var s = this.pCalculate(node.children[0]);
                var n = this.pCalculate(node.children[1]);
                return s.startsWith(n);
            }
            else if (node.value=='endswith')
            {
                var s = this.pCalculate(node.children[0]);
                var n = this.pCalculate(node.children[1]);
                return s.endsWith(n);
            }
            else if (node.value=='reverse')
            {
                var s = this.pCalculate(node.children[0]);
                return s.reverse();
            }

            //Validate
            else if (node.value=='is_dutchpostcode')
            {

                var s = this.pCalculate(node.children[0]);
                return cbForm.validateDutchPostcode(s);
            }
            else if (node.value=='is_email')
            {

                var s = this.pCalculate(node.children[0]);
                return cbForm.validateEmail(s);
            }
            else if (node.value=='is_url')
            {

                var s = this.pCalculate(node.children[0]);
                return cbForm.validateURL(s);
            }
            else if (node.value=='is_int')
            {

                var s = this.pCalculate(node.children[0]);
                return cbForm.validateInt(s);
            }
            else if (node.value=='is_uint')
            {
                var s = this.pCalculate(node.children[0]);
                return cbForm.validateUInt(s);
            }
            else if (node.value=='is_numeric')
            {
                var s = this.pCalculate(node.children[0]);
                return cbForm.validateNumeric(s);
            }
            else if (node.value=='is_unumeric')
            {
                var s = this.pCalculate(node.children[0]);
                return cbForm.validateUnsignedNumeric(s);
            }




        }
        else
        {
            var l = this.pCalculate(node.children[0]);
            if (node.value == tokenTypes.add)
            {

                var r = this.pCalculate(node.children[1]);
                consoleLog(l + ' + ' + r);
                r = l + r;
            }
            if (node.value == tokenTypes.subtract)
            {
                r = this.pCalculate(node.children[1]);
                consoleLog(l + ' - ' + r);
                r = l - r;
            }
            if (node.value == tokenTypes.multiply)
            {
                r = this.pCalculate(node.children[1]);
                consoleLog(l + ' * ' + r);
                r = l * r;
            }
            if (node.value == tokenTypes.divide)
            {

                r = this.pCalculate(node.children[1]);
                consoleLog(l + ' / ' + r);
                r = l / r;
            }
            if (node.value==tokenTypes.eq)
            {
                r = this.pCalculate(node.children[1]);
                r = (l == r);
            }
            if (node.value==tokenTypes.ne)
            {
                r = this.pCalculate(node.children[1]);
                r = (l != r);
            }
            if (node.value==tokenTypes.lt)
            {
                r = this.pCalculate(node.children[1]);
                r = (l < r);
            }
            if (node.value==tokenTypes.lte)
            {
                r = this.pCalculate(node.children[1]);
                r = (l <= r);
            }
            if (node.value==tokenTypes.gt)
            {
                r = this.pCalculate(node.children[1]);
                r = (l > r);
            }
            if (node.value==tokenTypes.gte)
            {
                r = this.pCalculate(node.children[1]);
                r = (l >= r);
            }
            if (node.value==tokenTypes.logand)
            {
                r = this.pCalculate(node.children[1]);
                r = (l && r);
            }
            if (node.value==tokenTypes.logor)
            {
                r = this.pCalculate(node.children[1]);
                r = (l || r);
            }
        }
        return r;
    }
}

