/// <summary> /// The last Rule is often a 'fallback' rule with an empty condition. If this is the case, /// we can sometimes perform an optimisation that reduces the overall code size. /// </summary> /// <returns>Root of the generated tree.</returns> private Node?BuildFallbackSequence() { // sanity check if (ruleSet.NumRules <= 1) { return(null); } // check that there is a fallback rule RuleSetEntry lastRule = ruleSet[ruleSet.NumRules - 1]; if (!lastRule.EffectiveCondition.IsEmpty) { return(null); } // check that sequence nodes are permitted if (!spec.Config.AllowSequence) { return(null); } if (spec.Config.Verbose) { Console.WriteLine("Performing fallback sequence optimisation."); } // remove the fallback rule and build the tree RuleSet rSet = ruleSet.DeriveExcludingLast(); var builder = new TreeBuilder(spec, rSet, this); Node node = builder.Build(); // ensure that there is a sequence node including the root // of the tree SequenceNode seq; if (node is SequenceNode) { seq = (SequenceNode)node; } else { seq = new SequenceNode(spec); seq.Append(node); } // now paste the fallback rule onto the end of the sequence seq.Append(lastRule.Rule); return(seq); }
/// <summary> /// Generate an if-else node for a Rule. /// </summary> private Node CreateIfElseNode(RuleSetEntry entry, Node elseBranch) { // generate a child node for the rule if (entry.EffectiveCondition.IsEmpty) { if (spec.Config.Verbose && !(elseBranch is EmptyNode)) { Console.WriteLine("Discarding non-empty else branch; condition is empty."); } return(entry.Rule); } else { if (spec.Config.NoOptimiseIfConditionNodes) { return(new IfElseNode(spec, entry.Rule.Condition, entry.Rule, elseBranch)); } else { return(new IfElseNode(spec, entry.EffectiveCondition, entry.Rule, elseBranch)); } } }