protected virtual bool TranslateLeftFactoredDecision(GrammarAST block, string factoredRule, bool variant, DecisionFactorMode mode, bool includeFactoredElement)
{
if (mode == DecisionFactorMode.PARTIAL_UNFACTORED && includeFactoredElement)
{
throw new ArgumentException("Cannot include the factored element in unfactored alternatives.");
}
else if (mode == DecisionFactorMode.COMBINED_FACTOR && !includeFactoredElement)
{
throw new ArgumentException("Cannot return a combined answer without the factored element.");
}
if (!ExpandOptionalQuantifiersForBlock(block, variant))
{
return false;
}
IList<GrammarAST> alternatives = block.GetAllChildrenWithType(ANTLRParser.ALT);
GrammarAST[] factoredAlternatives = new GrammarAST[alternatives.Count];
GrammarAST[] unfactoredAlternatives = new GrammarAST[alternatives.Count];
IntervalSet factoredIntervals = new IntervalSet();
IntervalSet unfactoredIntervals = new IntervalSet();
for (int i = 0; i < alternatives.Count; i++)
{
GrammarAST alternative = alternatives[i];
if (mode.IncludeUnfactoredAlts())
{
GrammarAST unfactoredAlt = TranslateLeftFactoredAlternative(alternative.DupTree(), factoredRule, variant, DecisionFactorMode.PARTIAL_UNFACTORED, false);
unfactoredAlternatives[i] = unfactoredAlt;
if (unfactoredAlt != null)
{
unfactoredIntervals.Add(i);
}
}
if (mode.IncludeFactoredAlts())
{
GrammarAST factoredAlt = TranslateLeftFactoredAlternative(alternative, factoredRule, variant, mode == DecisionFactorMode.COMBINED_FACTOR ? DecisionFactorMode.PARTIAL_FACTORED : DecisionFactorMode.FULL_FACTOR, includeFactoredElement);
factoredAlternatives[i] = factoredAlt;
if (factoredAlt != null)
{
factoredIntervals.Add(alternative.ChildIndex);
}
}
}
if (factoredIntervals.IsNil && !mode.IncludeUnfactoredAlts())
{
return false;
}
else if (unfactoredIntervals.IsNil && !mode.IncludeFactoredAlts())
{
return false;
}
if (unfactoredIntervals.IsNil && factoredIntervals.Count == alternatives.Count && mode.IncludeFactoredAlts() && !includeFactoredElement)
{
for (int i = 0; i < factoredAlternatives.Length; i++)
{
GrammarAST translatedAlt = factoredAlternatives[i];
if (translatedAlt.ChildCount == 0)
{
adaptor.AddChild(translatedAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
adaptor.SetChild(block, i, translatedAlt);
}
return true;
}
else if (factoredIntervals.IsNil && unfactoredIntervals.Count == alternatives.Count && mode.IncludeUnfactoredAlts())
{
for (int i = 0; i < unfactoredAlternatives.Length; i++)
{
GrammarAST translatedAlt = unfactoredAlternatives[i];
if (translatedAlt.ChildCount == 0)
{
adaptor.AddChild(translatedAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
adaptor.SetChild(block, i, translatedAlt);
}
return true;
}
if (mode == DecisionFactorMode.FULL_FACTOR)
{
return false;
}
/* for a, b, c being arbitrary `element` trees, this block performs
* this transformation:
*
* factoredElement a
* | factoredElement b
* | factoredElement c
* | ...
*
* ==>
*
* factoredElement (a | b | c | ...)
*/
GrammarAST newChildren = (GrammarAST)adaptor.Nil();
for (int i = 0; i < alternatives.Count; i++)
{
if (mode.IncludeFactoredAlts() && factoredIntervals.Contains(i))
{
bool combineWithPrevious = i > 0 && factoredIntervals.Contains(i - 1) && (!mode.IncludeUnfactoredAlts() || !unfactoredIntervals.Contains(i - 1));
if (combineWithPrevious)
{
GrammarAST translatedAlt = factoredAlternatives[i];
if (translatedAlt.ChildCount == 0)
{
adaptor.AddChild(translatedAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
GrammarAST previous = (GrammarAST)newChildren.GetChild(newChildren.ChildCount - 1);
#if false
if (LOGGER.isLoggable(Level.FINE))
{
LOGGER.log(Level.FINE, previous.ToStringTree());
LOGGER.log(Level.FINE, translatedAlt.ToStringTree());
}
#endif
if (previous.ChildCount == 1 || previous.GetChild(1).Type != ANTLRParser.BLOCK)
{
GrammarAST newBlock = new BlockAST(adaptor.CreateToken(ANTLRParser.BLOCK, "BLOCK"));
GrammarAST newAlt = new AltAST(adaptor.CreateToken(ANTLRParser.ALT, "ALT"));
adaptor.AddChild(newBlock, newAlt);
while (previous.ChildCount > 1)
{
adaptor.AddChild(newAlt, previous.DeleteChild(1));
}
if (newAlt.ChildCount == 0)
{
adaptor.AddChild(newAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
adaptor.AddChild(previous, newBlock);
}
if (translatedAlt.ChildCount == 1 || translatedAlt.GetChild(1).Type != ANTLRParser.BLOCK)
{
GrammarAST newBlock = new BlockAST(adaptor.CreateToken(ANTLRParser.BLOCK, "BLOCK"));
GrammarAST newAlt = new AltAST(adaptor.CreateToken(ANTLRParser.ALT, "ALT"));
adaptor.AddChild(newBlock, newAlt);
while (translatedAlt.ChildCount > 1)
{
adaptor.AddChild(newAlt, translatedAlt.DeleteChild(1));
}
if (newAlt.ChildCount == 0)
{
adaptor.AddChild(newAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
adaptor.AddChild(translatedAlt, newBlock);
}
GrammarAST combinedBlock = (GrammarAST)previous.GetChild(1);
adaptor.AddChild(combinedBlock, translatedAlt.GetChild(1).GetChild(0));
#if false
if (LOGGER.isLoggable(Level.FINE))
{
LOGGER.log(Level.FINE, previous.ToStringTree());
}
#endif
}
else
{
GrammarAST translatedAlt = factoredAlternatives[i];
if (translatedAlt.ChildCount == 0)
{
adaptor.AddChild(translatedAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
adaptor.AddChild(newChildren, translatedAlt);
}
}
if (mode.IncludeUnfactoredAlts() && unfactoredIntervals.Contains(i))
{
GrammarAST translatedAlt = unfactoredAlternatives[i];
if (translatedAlt.ChildCount == 0)
{
adaptor.AddChild(translatedAlt, adaptor.Create(ANTLRParser.EPSILON, "EPSILON"));
}
adaptor.AddChild(newChildren, translatedAlt);
}
}
adaptor.ReplaceChildren(block, 0, block.ChildCount - 1, newChildren);
if (!variant && block.Parent is RuleAST)
{
RuleAST ruleAST = (RuleAST)block.Parent;
string ruleName = ruleAST.GetChild(0).Text;
Rule r = _rules[ruleName];
IList<GrammarAST> blockAlts = block.GetAllChildrenWithType(ANTLRParser.ALT);
r.numberOfAlts = blockAlts.Count;
r.alt = new Alternative[blockAlts.Count + 1];
for (int i = 0; i < blockAlts.Count; i++)
{
r.alt[i + 1] = new Alternative(r, i + 1);
r.alt[i + 1].ast = (AltAST)blockAlts[i];
}
}
return true;
}