var DomUtils = require(“domutils”),

isTag       = DomUtils.isTag,
getParent   = DomUtils.getParent,
getChildren = DomUtils.getChildren,
getSiblings = DomUtils.getSiblings,
getName     = DomUtils.getName;

/*

all available rules

*/ module.exports = {

__proto__: null,

attribute: require("./attributes.js").compile,
pseudo: require("./pseudos.js").compile,

//tags
tag: function(next, data){
        var name = data.name;
        return function tag(elem){
                return getName(elem) === name && next(elem);
        };
},

//traversal
descendant: function(next, rule, options, context, acceptSelf){
        return function descendant(elem){

                if (acceptSelf && next(elem)) return true;

                var found = false;

                while(!found && (elem = getParent(elem))){
                        found = next(elem);
                }

                return found;
        };
},
parent: function(next, data, options){
        if(options && options.strict) throw SyntaxError("Parent selector isn't part of CSS3");

        return function parent(elem){
                return getChildren(elem).some(test);
        };

        function test(elem){
                return isTag(elem) && next(elem);
        }
},
child: function(next){
        return function child(elem){
                var parent = getParent(elem);
                return !!parent && next(parent);
        };
},
sibling: function(next){
        return function sibling(elem){
                var siblings = getSiblings(elem);

                for(var i = 0; i < siblings.length; i++){
                        if(isTag(siblings[i])){
                                if(siblings[i] === elem) break;
                                if(next(siblings[i])) return true;
                        }
                }

                return false;
        };
},
adjacent: function(next){
        return function adjacent(elem){
                var siblings = getSiblings(elem),
                    lastElement;

                for(var i = 0; i < siblings.length; i++){
                        if(isTag(siblings[i])){
                                if(siblings[i] === elem) break;
                                lastElement = siblings[i];
                        }
                }

                return !!lastElement && next(lastElement);
        };
},
universal: function(next){
        return next;
}

};