private void parse()

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);
    }
  }