in base/src/main/java/org/arend/naming/binOp/MetaBinOpParser.java [73:185]
private void parse(int start, int end) {
if (start == end) {
return;
}
int conflictIndex = -1;
int minIndex = -1;
Precedence minPrecedence = Precedence.DEFAULT;
List<Concrete.BinOpSequenceElem<Concrete.Expression>> sequence = myExpression.getSequence();
for (int i = start; i < end; i++) {
ResolvedReference resolvedRef = myResolvedReferences.get(i);
if (resolvedRef == null) {
continue;
}
Concrete.BinOpSequenceElem<Concrete.Expression> elem = sequence.get(i);
Precedence precedence = resolvedRef.refExpr.getReferent() instanceof GlobalReferable ? ((GlobalReferable) resolvedRef.refExpr.getReferent()).getPrecedence() : null;
if (elem.fixity == Fixity.INFIX || elem.fixity == Fixity.POSTFIX || elem.fixity == Fixity.UNKNOWN && precedence != null && precedence.isInfix) {
if (precedence == null) {
precedence = Precedence.DEFAULT;
}
if (minIndex != -1) {
PartialComparator.Result cmp = sequence.get(minIndex).fixity == Fixity.POSTFIX ? PartialComparator.Result.GREATER : comparePrecedence(minPrecedence, precedence);
if (cmp == PartialComparator.Result.UNCOMPARABLE && elem.fixity == Fixity.POSTFIX) {
if (minPrecedence.associativity == Precedence.Associativity.LEFT_ASSOC) {
cmp = PartialComparator.Result.GREATER;
} else if (minPrecedence.associativity == Precedence.Associativity.RIGHT_ASSOC) {
cmp = PartialComparator.Result.LESS;
}
}
if (cmp == PartialComparator.Result.LESS) {
continue;
}
if (cmp == PartialComparator.Result.UNCOMPARABLE) {
conflictIndex = minIndex;
}
}
minIndex = i;
minPrecedence = precedence;
}
}
if (minIndex == -1) {
ResolvedReference firstRef = myResolvedReferences.get(start);
MetaResolver meta = firstRef == null ? null : ExpressionResolveNameVisitor.getMetaResolver(firstRef.refExpr.getReferent());
if (meta != null) {
myVisitor.finalizeReference(sequence.get(start), firstRef);
List<Concrete.Argument> args = new ArrayList<>(end - start - 1);
for (int i = start + 1; i < end; i++) {
resetReference(sequence.get(i), myResolvedReferences.get(i));
args.add(new Concrete.Argument(sequence.get(i).getComponent(), sequence.get(i).isExplicit));
}
myClausesHandled = true;
myResult.add(new Concrete.BinOpSequenceElem<>(myVisitor.convertMetaResult(meta.resolvePrefix(myVisitor, new ContextDataImpl(firstRef.refExpr, args, myCoclauses, myExpression.getClauses(), null, null)), firstRef.refExpr, args, null, myExpression.getClauses())));
} else {
for (int i = start; i < end; i++) {
boolean isRef = sequence.get(i).getComponent() instanceof Concrete.ReferenceExpression;
myVisitor.finalizeReference(sequence.get(i), myResolvedReferences.get(i));
if (isRef) {
Concrete.BinOpSequenceElem<Concrete.Expression> elem = sequence.get(i);
Concrete.Expression function = elem.getComponent() instanceof Concrete.AppExpression ? ((Concrete.AppExpression) elem.getComponent()).getFunction() : elem.getComponent();
if (function instanceof Concrete.ReferenceExpression) {
elem.setComponent(myVisitor.invokeMetaWithoutArguments((Concrete.ReferenceExpression) function, elem.getComponent() instanceof Concrete.AppExpression ? ((Concrete.AppExpression) elem.getComponent()).getArguments().get(0).expression : null, true));
}
}
myResult.add(sequence.get(i));
}
}
return;
}
MetaResolver minMeta = ExpressionResolveNameVisitor.getMetaResolver(myResolvedReferences.get(minIndex).refExpr.getReferent());
if (conflictIndex != -1 && (minMeta != null || ExpressionResolveNameVisitor.getMetaResolver(myResolvedReferences.get(conflictIndex).refExpr.getReferent()) != null)) {
myVisitor.getErrorReporter().report(new PrecedenceError(myResolvedReferences.get(conflictIndex).refExpr.getReferent(), null, myResolvedReferences.get(minIndex).refExpr.getReferent(), null, myResolvedReferences.get(minMeta != null ? minIndex : conflictIndex).refExpr));
}
if (minMeta != null) {
Concrete.ReferenceExpression refExpr = myResolvedReferences.get(minIndex).refExpr;
myVisitor.finalizeReference(sequence.get(minIndex), myResolvedReferences.get(minIndex));
for (int i = start; i < end; i++) {
if (i != minIndex) {
resetReference(myExpression.getSequence().get(i), myResolvedReferences.get(i));
}
}
ConcreteExpression metaResult;
Concrete.Expression leftArg = start == minIndex ? null : new Concrete.BinOpSequenceExpression(myExpression.getData(), sequence.subList(start, minIndex), null);
List<Concrete.Argument> resultArgs = binOpSeqToArgs(sequence, start, minIndex);
List<Concrete.Argument> args = binOpSeqToArgs(sequence, minIndex + 1, end);
resultArgs.addAll(args);
myVisitor.getErrorReporter().resetErrorsNumber();
if (sequence.get(minIndex).fixity == Fixity.POSTFIX) {
metaResult = minMeta.resolvePostfix(myVisitor, new ContextDataImpl(refExpr, args, null, null, null, null), leftArg);
} else {
int i = minIndex + 1;
List<Concrete.Argument> implicitArgs = new ArrayList<>();
for (; i < end; i++) {
if (sequence.get(i).isExplicit) {
break;
}
implicitArgs.add(new Concrete.Argument(sequence.get(i).getComponent(), false));
}
metaResult = minMeta.resolveInfix(myVisitor, new ContextDataImpl(refExpr, implicitArgs, null, null, null, null), leftArg, i >= end ? null : new Concrete.BinOpSequenceExpression(myExpression.getData(), sequence.subList(i, end), null));
}
myResult.add(new Concrete.BinOpSequenceElem<>(myVisitor.convertMetaResult(metaResult, refExpr, resultArgs, null, null)));
} else {
parse(start, minIndex);
myVisitor.finalizeReference(sequence.get(minIndex), myResolvedReferences.get(minIndex));
myResult.add(sequence.get(minIndex));
parse(minIndex + 1, end);
}
}