public override void FinishGrammar(GrammarRootAST root, GrammarAST ID)
{
Runtime.Misc.MultiMap<string, Rule> baseContexts = new Runtime.Misc.MultiMap<string, Rule>();
foreach (Rule r in ruleCollector.rules.Values)
{
GrammarAST optionAST = r.ast.GetOptionAST("baseContext");
if (r.ast.IsLexerRule())
{
if (optionAST != null)
{
IToken errorToken = optionAST.Token;
g.tool.errMgr.GrammarError(ErrorType.LEXER_RULE_CANNOT_HAVE_BASE_CONTEXT,
g.fileName, errorToken, r.name);
}
continue;
}
baseContexts.Map(r.GetBaseContext(), r);
if (optionAST != null)
{
Rule targetRule;
ruleCollector.rules.TryGetValue(r.GetBaseContext(), out targetRule);
bool targetSpecifiesBaseContext =
targetRule != null
&& targetRule.ast != null
&& (targetRule.ast.GetOptionAST("baseContext") != null
|| !targetRule.name.Equals(targetRule.GetBaseContext()));
if (targetSpecifiesBaseContext)
{
IToken errorToken = optionAST.Token;
g.tool.errMgr.GrammarError(ErrorType.BASE_CONTEXT_CANNOT_BE_TRANSITIVE,
g.fileName, errorToken, r.name);
}
}
// It's unlikely for this to occur when optionAST is null, but checking
// anyway means it can detect certain errors within the logic of the
// Tool itself.
if (!ruleCollector.rules.ContainsKey(r.GetBaseContext()))
{
IToken errorToken;
if (optionAST != null)
{
errorToken = optionAST.Token;
}
else
{
errorToken = ((CommonTree)r.ast.GetChild(0)).Token;
}
g.tool.errMgr.GrammarError(ErrorType.BASE_CONTEXT_MUST_BE_RULE_NAME,
g.fileName, errorToken, r.name);
}
}
foreach (KeyValuePair<string, IList<Rule>> entry in baseContexts)
{
// suppress RULE_WITH_TOO_FEW_ALT_LABELS_GROUP if RULE_WITH_TOO_FEW_ALT_LABELS
// would already have been reported for at least one rule with this
// base context.
bool suppressError = false;
int altLabelCount = 0;
int outerAltCount = 0;
foreach (Rule rule in entry.Value)
{
outerAltCount += rule.numberOfAlts;
IList<GrammarAST> altLabels;
if (ruleCollector.ruleToAltLabels.TryGetValue(rule.name, out altLabels) && altLabels != null && altLabels.Count > 0)
{
if (altLabels.Count != rule.numberOfAlts)
{
suppressError = true;
break;
}
altLabelCount += altLabels.Count;
}
}
if (suppressError)
{
continue;
}
if (altLabelCount != 0 && altLabelCount != outerAltCount)
{
Rule errorRule = entry.Value[0];
g.tool.errMgr.GrammarError(ErrorType.RULE_WITH_TOO_FEW_ALT_LABELS_GROUP,
g.fileName, ((CommonTree)errorRule.ast.GetChild(0)).Token, errorRule.name);
}
}
}