I would suggest you try to go away using actual boolean expressions and figure out what actions or events you're doing to the "system" that you're developing. If you're using if-statements you might as well use a scripting language.
Once upon a time I've created a DSL in JSON format that defined rules as actions or events instead of using boolean expressions. I chose JSON because the DSL code was generated from a web backend and was going to be used in a javascript web front end.
Consider a series of options one user can take in a designer UI, all individually identifiable by a name. The designer UI for the example below will be cars that the user can select. The DSL basically looked like this:
// an array of rules
"rules": [
// rule number 1
{
// the originating option of the event or action
"source": "car_1",
// the option(s) that receives of the action or event
"destination": ["color_yellow", "color_blue"],
// the event or action that should happen
// in this case the destination should be disabled
"action": "disable",
// what to roll back to if the destination was selected
"instead": "color_red"
},
// rule number 2, same as above but used to
// demonstrate chaining
{
"source": "roof_sunroof",
"destination": "color_red",
"action": "disable",
"instead": "color_green"
},
... and so on
]
In this example, in the first rule: if the user selected the option "car_1" the color options "color_yellow" and "color_blue" will be disabled (because that particular car does not come in yellow and blue colors). In the second rule, if the user selects "roof_sunroof", then the option of "color_red" is disabled.
Meanwhile the front-end would take this JSON file and create all the options on the User Interface and use the rules array to determine which events to set up.
The actions and events were implemented in such extend that they were chainable by the rule set, so if one source would disable and the roll back option was also disabled, the event would look up what to roll back to instead. In the example above if the option "roof_sunroof" was selected and then "car_1", the application would first try to rollback to "color_red" (which is disabled) and then to "color_green". If there was any circular dependencies, it would most likely be a bug in the DSL rather in the designer UI. Note that the events enforce the rules without the need to build a complex tree.
On the back-end side, it's easier to represent the rules as objects if they're definitions for a DSL. Sure if you go the if-statement route, you could persist the rule as a text script.