in src/org/intellij/grammar/generator/ExpressionHelper.java [135:232]
private void buildOperatorMap(BnfRule rule, BnfRule rootRule, ExpressionInfo expressionInfo) {
Map<PsiElement, RuleGraphHelper.Cardinality> ruleContent = myRuleGraph.getFor(rule);
RuleGraphHelper.Cardinality cardinality = ruleContent.get(rootRule);
BnfRule rootRuleSubst = rootRule;
if (cardinality == null) {
Collection<BnfRule> extendsRules = myRuleGraph.getExtendsRules(rootRule);
JBIterable<BnfRule> tryOtherRules = JBIterable.from(ruleContent.keySet())
.filter(BnfRule.class)
.filter(extendsRules::contains)
.append(getSuperRules(myFile, rootRule).filter(Conditions.notNull()));
for (BnfRule r : tryOtherRules) {
cardinality = ruleContent.get(r);
if (cardinality == null) continue;
rootRuleSubst = r;
break;
}
}
if (Rule.isExternal(rule)) {
BnfExpression expression = (BnfExpression)ContainerUtil.getFirstItem(ruleContent.keySet());
expressionInfo.operatorMap.put(rule, new OperatorInfo(rule, OperatorType.ATOM, expression, null));
return;
}
String rootRuleName = rootRule.getName();
List<BnfExpression> childExpressions = getChildExpressions(rule.getExpression());
OperatorInfo info;
if (cardinality == null) {
// atom
info = new OperatorInfo(rule, OperatorType.ATOM, rule.getExpression(), null);
}
else if (childExpressions.size() < 2) {
addWarning("invalid expression definition for " + rule + ": 2 or more arguments expected");
info = new OperatorInfo(rule, OperatorType.ATOM, rule.getExpression(), null);
}
else if (cardinality == RuleGraphHelper.Cardinality.REQUIRED) {
// postfix or prefix unary expression
int index = indexOf(rootRuleSubst, 0, childExpressions, expressionInfo);
BnfRule arg1 = substRule(childExpressions, index, rootRule);
if (index == 0) {
info = new OperatorInfo(rule, OperatorType.POSTFIX, combine(childExpressions.subList(1, childExpressions.size())), null, arg1, null);
}
else if (index == -1) {
addWarning(rule +": " + rootRuleName + " reference not found, treating as ATOM");
info = new OperatorInfo(rule, OperatorType.ATOM, rule.getExpression(), null);
}
else {
info = new OperatorInfo(rule, OperatorType.PREFIX, combine(childExpressions.subList(0, index)),
combine(childExpressions.subList(index + 1, childExpressions.size())), arg1, null);
}
}
else if (cardinality == RuleGraphHelper.Cardinality.AT_LEAST_ONE) {
// binary or n-ary expression
int index1 = indexOf(rootRuleSubst, 0, childExpressions, expressionInfo);
int index2 = indexOf(rootRuleSubst, 1, childExpressions, expressionInfo);
if (index1 != 0) {
addWarning(rule +": binary or n-ary expression cannot have prefix, treating as ATOM");
info = new OperatorInfo(rule, OperatorType.ATOM, rule.getExpression(), null);
}
else if (index2 == 1) {
addWarning(rule + ": binary expression needs operator, treating as ATOM");
info = new OperatorInfo(rule, OperatorType.ATOM, rule.getExpression(), null);
}
else {
BnfRule arg1 = substRule(childExpressions, index1, rootRule);
if (index2 == -1) {
BnfExpression lastExpression = childExpressions.get(1);
boolean badNAry = childExpressions.size() != 2 || !(lastExpression instanceof BnfQuantified) ||
!(((BnfQuantified)lastExpression).getQuantifier().getText().equals("+")) ||
!(((BnfQuantified)lastExpression).getExpression() instanceof BnfParenExpression);
List<BnfExpression> childExpressions2 = badNAry ? Collections.emptyList() :
getChildExpressions(
((BnfParenExpression)((BnfQuantified)lastExpression).getExpression()).getExpression());
int index3 = indexOf(rootRuleSubst, 0, childExpressions2, expressionInfo);
if (badNAry || index3 == -1) {
addWarning(
rule + ": '" + rootRuleName + " ( <op> " + rootRuleName + ") +' expected for N-ary operator, treating as POSTFIX"
);
info = new OperatorInfo(rule, OperatorType.POSTFIX, combine(childExpressions.subList(1, childExpressions.size())), null,
arg1, null);
}
else {
BnfRule arg2 = substRule(childExpressions2, index3, rootRule);
info = new OperatorInfo(rule, OperatorType.N_ARY, combine(childExpressions2.subList(0, index3)),
combine(childExpressions2.subList(index3 + 1, childExpressions2.size())), arg1, arg2);
}
}
else {
BnfRule arg2 = substRule(childExpressions, index2, rootRule);
info = new OperatorInfo(rule, OperatorType.BINARY, combine(childExpressions.subList(index1 + 1, index2)),
combine(childExpressions.subList(index2 + 1, childExpressions.size())), arg1, arg2);
}
}
}
else {
addWarning(rule +": unexpected cardinality " + cardinality + " of " + rootRuleName +", treating as ATOM");
info = new OperatorInfo(rule, OperatorType.ATOM, rule.getExpression(), null);
}
expressionInfo.operatorMap.put(rule, info);
}