public string visit(BinOp node)
        {
            int left   = Convert.ToInt32(node.left.accept(this));
            int right  = Convert.ToInt32(node.right.accept(this));
            int result = 0;

            switch (node.token.type)
            {
            case Tokens.PLUS:
                result = left + right;
                break;

            case Tokens.MINUS:
                result = left - right;
                break;

            case Tokens.MUL:
                result = left * right;
                break;

            case Tokens.DIV:
                result = left / right;
                break;

            case Tokens.LT:
                result = bool2int(left < right);
                break;

            case Tokens.GT:
                result = bool2int(left > right);
                break;

            case Tokens.GEQ:
                result = bool2int(left >= right);
                break;

            case Tokens.LEQ:
                result = bool2int(left <= right);
                break;

            case Tokens.ISEQ:
                result = bool2int(left == right);
                break;

            case Tokens.NEQ:
                result = bool2int(left != right);
                break;

            case Tokens.AND:
                result = bool2int(left != 0 && right != 0);
                break;

            case Tokens.OR:
                result = bool2int(left != 0 || right != 0);
                break;
            }
            return(Convert.ToString(result));
        }
        //orexpr : compexpr ((AND) compexpr)*
        private AST andexpr()
        {
            AST node = compexpr();

            while (current_token.type == Tokens.AND)
            {
                Token t = current_token;
                eat(Tokens.AND);
                node = new BinOp(node, t, compexpr());
            }
            return(node);
        }
        //orexpr : andexpr ((OR) andexpr)*
        private AST orexpr()
        {
            AST node = andexpr();

            while (current_token.type == Tokens.OR)
            {
                Token t = current_token;
                eat(Tokens.OR);
                node = new BinOp(node, t, andexpr());
            }
            return(node);
        }
        //mulexpr : factor ((MUL|DIV) factor)*
        private AST mulexpr()
        {
            AST node = factor();

            Tokens[] addition_operators = new Tokens[] { Tokens.MUL, Tokens.DIV };
            while (Array.IndexOf(addition_operators, current_token.type) != -1)
            {
                Token t = current_token;
                eat(current_token.type);
                node = new BinOp(node, t, factor());
            }
            return(node);
        }
        //sumexpr : mulexpr ((PLUS|MINUS) mulexpr)*
        private AST sumexpr()
        {
            AST node = mulexpr();

            Tokens[] addition_operators = new Tokens[] { Tokens.PLUS, Tokens.MINUS };
            while (Array.IndexOf(addition_operators, current_token.type) != -1)
            {
                Token t = current_token;
                eat(current_token.type);
                node = new BinOp(node, t, mulexpr());
            }
            return(node);
        }