.nud     Null denotation .fud     First null denotation .led     Left denotation lbp     Left binding power rbp     Right binding power They are elements of the parsing method called Top Down Operator Precedence.
356098
function expression(rbp, initial) {

// rbp is the right binding power.
// initial indicates that this is the first expression of a statement.

        var left;
        if (next_token.id === '(end)') {
            stop('unexpected_a', token, next_token.id);
        }
        advance();
        if (option.safe && scope[token.string] &&
                scope[token.string] === global_scope[token.string] &&
                (next_token.id !== '(' && next_token.id !== '.')) {
            warn('adsafe_a', token);
        }
        if (initial) {
            anonname = 'anonymous';
            funct['(verb)'] = token.string;
        }
        if (initial === true && token.fud) {
            left = token.fud();
        } else {
            if (token.nud) {
                left = token.nud();
            } else {
                if (next_token.id === '(number)' && token.id === '.') {
                    warn('leading_decimal_a', token, artifact());
                    advance();
                    return token;
                }
                stop('expected_identifier_a', token, token.id);
            }
            while (rbp < next_token.lbp) {
                advance();
                if (token.led) {
                    left = token.led(left);
                } else {
                    stop('expected_operator_a', token, token.id);
                }
            }
        }
        return left;
    }
948762
function B(iid, op, left, right, flags) {
        var bFlags = decodeBitPattern(flags, 3); // [isComputed, isOpAssign, isSwitchCaseComparison]
        var result, aret, skip = false;

        if (sandbox.analysis && sandbox.analysis.binaryPre) {
            aret = sandbox.analysis.binaryPre(iid, op, left, right, bFlags[1], bFlags[2], bFlags[0]);
            if (aret) {
                op = aret.op;
                left = aret.left;
                right = aret.right;
                skip = aret.skip;
            }
        }


        if (!skip) {
            switch (op) {
                case "+":
                    result = left + right;
                    break;
                case "-":
                    result = left - right;
                    break;
                case "*":
                    result = left * right;
                    break;
                case "/":
                    result = left / right;
                    break;
                case "%":
                    result = left % right;
                    break;
                case "<<":
                    result = left << right;
                    break;
                case ">>":
                    result = left >> right;
                    break;
                case ">>>":
                    result = left >>> right;
                    break;
                case "<":
                    result = left < right;
                    break;
                case ">":
                    result = left > right;
                    break;
                case "<=":
                    result = left <= right;
                    break;
                case ">=":
                    result = left >= right;
                    break;
                case "==":
                    result = left == right;
                    break;
                case "!=":
                    result = left != right;
                    break;
                case "===":
                    result = left === right;
                    break;
                case "!==":
                    result = left !== right;
                    break;
                case "&":
                    result = left & right;
                    break;
                case "|":
                    result = left | right;
                    break;
                case "^":
                    result = left ^ right;
                    break;
                case "delete":
                    result = delete left[right];
                    break;
                case "instanceof":
                    result = left instanceof right;
                    break;
                case "in":
                    result = left in right;
                    break;
                default:
                    throw new Error(op + " at " + iid + " not found");
                    break;
            }
        }

        if (sandbox.analysis && sandbox.analysis.binary) {
            aret = sandbox.analysis.binary(iid, op, left, right, result, bFlags[1], bFlags[2], bFlags[0]);
            if (aret) {
                result = aret.result;
            }
        }
        return (lastComputedValue = result);
    }
551787
def p_null_literal(self, p):
        """"""
        p[0] = self.asttypes.Null(p[1])
        p[0].setpos(p)
404192
Nullness standardFieldNullness(
      ClassAndField accessed, @Nullable AccessPath path, AccessPathValues<Nullness> store) {
    // First, check the store for a dataflow-computed nullness value and return it if it exists
    // Otherwise, check for nullness annotations on the field's symbol (including type annotations)
    // If there are none, check for nullness annotations on generic type bounds, if any
    // If there are none, fall back to the defaultAssumption

    Nullness dataflowResult = (path == null) ? BOTTOM : store.valueOfAccessPath(path, BOTTOM);
    if (dataflowResult != BOTTOM) {
      return dataflowResult;
    }

    Optional<Nullness> declaredNullness = NullnessAnnotations.fromAnnotationsOn(accessed.symbol);
    return declaredNullness.orElseGet(
        () -> NullnessAnnotations.getUpperBound(accessed.symbol.type).orElse(defaultAssumption));
  }
222159
function getUpperFunction(node) {
    for (let currentNode = node; currentNode; currentNode = currentNode.parent) {
        if (anyFunctionPattern.test(currentNode.type)) {
            return currentNode;
        }
    }
    return null;
}
686750
@Override
    public void foundGuaranteedNullDeref(@Nonnull
            Set<Location> assignedNullLocationSet, @Nonnull
            Set<Location> derefLocationSet, SortedSet<Location> doomedLocations, ValueNumberDataflow vna, ValueNumber refValue,
            @CheckForNull
            BugAnnotation variableAnnotation, NullValueUnconditionalDeref deref, boolean npeIfStatementCovered) {
        if (refValue.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) {
            return;
        }

        if (DEBUG) {
            System.out.println("Found guaranteed null deref in " + method.getName());
            for (Location loc : doomedLocations) {
                System.out.println("Doomed at " + loc);
            }
        }

        String bugType;

        int priority = npeIfStatementCovered ? HIGH_PRIORITY : NORMAL_PRIORITY;

        if (deref.isMethodReturnValue()) {
            if (deref.isReadlineValue()) {
                bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
            } else {
                bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";
            }
        } else if (derefLocationSet.size() > 1) {
            if (!deref.isAlwaysOnExceptionPath()) {
                bugType = "NP_GUARANTEED_DEREF";
            } else {
                bugType = "NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH";
            }
        } else if (!deref.isAlwaysOnExceptionPath()) {
            bugType = "NP_NULL_ON_SOME_PATH";
        } else {
            bugType = "NP_NULL_ON_SOME_PATH_EXCEPTION";
        }

        boolean allCallToAssertionMethod = !doomedLocations.isEmpty();
        for (Location loc : doomedLocations) {
            if (!callToAssertionMethod(loc)) {
                allCallToAssertionMethod = false;
            }
        }
        if (allCallToAssertionMethod) {
            return;
        }

        // Add Locations in the set of locations at least one of which
        // is guaranteed to be dereferenced

        SortedSet<Location> sourceLocations;
        if (doomedLocations.isEmpty() || doomedLocations.size() > 3 && doomedLocations.size() > assignedNullLocationSet.size()) {
            sourceLocations = new TreeSet<>(assignedNullLocationSet);
        } else {
            sourceLocations = doomedLocations;
        }

        if (doomedLocations.isEmpty() || derefLocationSet.isEmpty()) {
            return;
        }

        WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<>();

        addPropertiesForDereferenceLocations(propertySet, derefLocationSet, false);

        int minDereferencePC = minPC(derefLocationSet);
        int distance1 = minDereferencePC - maxPC(assignedNullLocationSet);
        int distance2 = minDereferencePC - maxPC(doomedLocations);
        int distance = Math.max(distance1, distance2);
        /*
        if (false) {
            System.out.printf("%9d %9d %9d RANGE %s.%s%s\n", distance, distance1, distance2, classContext.getClassDescriptor()
                    .toDottedClassName(), method.getName(), method.getSignature());
        }
         */

        // Create BugInstance

        BitSet knownNull = new BitSet();

        SortedSet<SourceLineAnnotation> knownNullLocations = new TreeSet<>();
        for (Location loc : sourceLocations) {
            SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc);
            if (sourceLineAnnotation == null) {
                continue;
            }
            int startLine = sourceLineAnnotation.getStartLine();
            if (startLine == -1) {
                knownNullLocations.add(sourceLineAnnotation);
            } else if (!knownNull.get(startLine)) {
                knownNull.set(startLine);
                knownNullLocations.add(sourceLineAnnotation);
            }
        }

        FieldAnnotation storedField = null;
        MethodAnnotation invokedMethod = null;
        XMethod invokedXMethod = null;
        int parameterNumber = -1;
        if (derefLocationSet.size() == 1) {

            Location loc = derefLocationSet.iterator().next();

            PointerUsageRequiringNonNullValue pu = null;
            try {
                UsagesRequiringNonNullValues usages = classContext.getUsagesRequiringNonNullValues(method);
                pu = usages.get(loc, refValue, vnaDataflow);
            } catch (DataflowAnalysisException e) {
                AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
            } catch (CFGBuilderException e) {
                AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
            }

            if (pu == null) {
                assert true; // nothing to do
            } else if (deref.isReadlineValue()) {
                bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
                priority = NORMAL_PRIORITY;
            } else if (deref.isMethodReturnValue() && !deref.isReadlineValue()) {
                bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";
                priority = NORMAL_PRIORITY;
            } else if (pu.isReturnFromNonNullMethod()) {
                bugType = "NP_NONNULL_RETURN_VIOLATION";
                String methodName = method.getName();
                String methodSig = method.getSignature();
                if ("clone".equals(methodName) && "()Ljava/lang/Object;".equals(methodSig)) {
                    bugType = "NP_CLONE_COULD_RETURN_NULL";
                    priority = NORMAL_PRIORITY;
                } else if ("toString".equals(methodName) && "()Ljava/lang/String;".equals(methodSig)) {
                    bugType = "NP_TOSTRING_COULD_RETURN_NULL";
                    priority = NORMAL_PRIORITY;
                }

            } else {
                XField f = pu.getNonNullField();
                if (f != null) {
                    storedField = FieldAnnotation.fromXField(f);
                    bugType = "NP_STORE_INTO_NONNULL_FIELD";
                } else {
                    XMethodParameter mp = pu.getNonNullParameter();
                    if (mp != null) {
                        invokedXMethod = mp.getMethod();
                        for (Location derefLoc : derefLocationSet) {
                            if (safeCallToPrimateParseMethod(invokedXMethod, derefLoc)) {
                                return;
                            }
                        }
                        invokedMethod = MethodAnnotation.fromXMethod(mp.getMethod());
                        if (mp.getParameterNumber() == 0
                                && TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(invokedXMethod)) {
                            return;
                        }
                        parameterNumber = mp.getParameterNumber();
                        bugType = "NP_NULL_PARAM_DEREF";
                    }
                }
            }
        }

        boolean hasManyNullTests = true;
        for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations) {
            if (!hasManyPreceedingNullTests(sourceLineAnnotation.getStartBytecode())) {
                hasManyNullTests = false;
            }
        }
        if (hasManyNullTests) {
            if ("NP_NULL_ON_SOME_PATH".equals(bugType) || "NP_GUARANTEED_DEREF".equals(bugType)) {
                bugType = "NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE";
            } else {
                priority++;
            }
        }

        BugInstance bugInstance = new BugInstance(this, bugType, priority).addClassAndMethod(classContext.getJavaClass(), method);
        if (invokedMethod != null) {
            assert invokedXMethod != null;
            XMethod i = invokedXMethod.resolveAccessMethodForMethod();
            if (i != invokedXMethod) {
                bugInstance.addMethod(i).describe(MethodAnnotation.METHOD_CALLED);
            } else {
                bugInstance.addMethod(invokedMethod).describe(MethodAnnotation.METHOD_CALLED)
                .addParameterAnnotation(parameterNumber, "INT_MAYBE_NULL_ARG");
            }
        }
        if (storedField != null) {
            bugInstance.addField(storedField).describe("FIELD_STORED");
        }
        bugInstance.addOptionalAnnotation(variableAnnotation);
        if (variableAnnotation instanceof FieldAnnotation) {
            bugInstance.describe("FIELD_CONTAINS_VALUE");
        }

        addPropertiesForDereferenceLocations(propertySet, derefLocationSet, false);

        if (deref.isAlwaysOnExceptionPath()) {
            propertySet.addProperty(NullDerefProperty.ALWAYS_ON_EXCEPTION_PATH);
        }

        if (!assignedNullLocationSet.isEmpty() && distance > 100) {
            propertySet.addProperty(NullDerefProperty.LONG_RANGE_NULL_SOURCE);
        }

        propertySet.decorateBugInstance(bugInstance);

        if ("NP_DEREFERENCE_OF_READLINE_VALUE".equals(bugType)) {

            int source = -9999;
            if (knownNullLocations.size() == 1) {
                source = knownNullLocations.iterator().next().getEndBytecode();
            }
            for (Location loc : derefLocationSet) {
                int pos = loc.getHandle().getPosition();
                if (pos != source + 3) {
                    // another detector
                    bugAccumulator.accumulateBug(bugInstance,
                            SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc));
                }
            }

        } else {
            for (Location loc : derefLocationSet) {
                bugInstance.addSourceLine(classContext, method, loc).describe(getDescription(loc, refValue));
            }

            if (sourceLocations == doomedLocations && assignedNullLocationSet.size() == 1) {
                Location assignedNull = assignedNullLocationSet.iterator().next();
                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method,
                        assignedNull);
                if (sourceLineAnnotation != null) {
                    int startLine = sourceLineAnnotation.getStartLine();
                    if (startLine > 0 && !knownNull.get(startLine)) {
                        bugInstance.add(sourceLineAnnotation).describe("SOURCE_LINE_NULL_VALUE");
                    }
                }

            }
            for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations) {
                bugInstance.add(sourceLineAnnotation).describe("SOURCE_LINE_KNOWN_NULL");
            }

            // Report it
            bugReporter.reportBug(bugInstance);
        }
    }
1002536
function validateNode(node, leftSide) {

            /*
             * When the left part of a binary expression is a single expression wrapped in
             * parentheses (ex: `(a) + b`), leftToken will be the last token of the expression
             * and operatorToken will be the closing parenthesis.
             * The leftToken should be the last closing parenthesis, and the operatorToken
             * should be the token right after that.
             */
            const operatorToken = sourceCode.getTokenAfter(leftSide, astUtils.isNotClosingParenToken);
            const leftToken = sourceCode.getTokenBefore(operatorToken);
            const rightToken = sourceCode.getTokenAfter(operatorToken);
            const operator = operatorToken.value;
            const operatorStyleOverride = styleOverrides[operator];
            const style = operatorStyleOverride || globalStyle;
            const fix = getFixer(operatorToken, style);

            // if single line
            if (astUtils.isTokenOnSameLine(leftToken, operatorToken) &&
                    astUtils.isTokenOnSameLine(operatorToken, rightToken)) {

                // do nothing.

            } else if (operatorStyleOverride !== "ignore" && !astUtils.isTokenOnSameLine(leftToken, operatorToken) &&
                    !astUtils.isTokenOnSameLine(operatorToken, rightToken)) {

                // lone operator
                context.report({
                    node,
                    loc: {
                        line: operatorToken.loc.end.line,
                        column: operatorToken.loc.end.column
                    },
                    message: "Bad line breaking before and after '{{operator}}'.",
                    data: {
                        operator
                    },
                    fix
                });

            } else if (style === "before" && astUtils.isTokenOnSameLine(leftToken, operatorToken)) {

                context.report({
                    node,
                    loc: {
                        line: operatorToken.loc.end.line,
                        column: operatorToken.loc.end.column
                    },
                    message: "'{{operator}}' should be placed at the beginning of the line.",
                    data: {
                        operator
                    },
                    fix
                });

            } else if (style === "after" && astUtils.isTokenOnSameLine(operatorToken, rightToken)) {

                context.report({
                    node,
                    loc: {
                        line: operatorToken.loc.end.line,
                        column: operatorToken.loc.end.column
                    },
                    message: "'{{operator}}' should be placed at the end of the line.",
                    data: {
                        operator
                    },
                    fix
                });

            } else if (style === "none") {

                context.report({
                    node,
                    loc: {
                        line: operatorToken.loc.end.line,
                        column: operatorToken.loc.end.column
                    },
                    message: "There should be no line break before or after '{{operator}}'.",
                    data: {
                        operator
                    },
                    fix
                });

            }
        }
746375
@SuppressWarnings("rawtypes")
    private static Object findFirstNonNull(Iterator it) {
        Object result = null;
        while(it.hasNext()) {
            result = it.next();
            if(result != null) {
                break;
            }
        }
        return result;
    }
932876
function(context: ParserContext): ?Token {
    if (
      !util.IsFollowsRuleSatisfied(
        context.getTokenWalker(),
        [
          { token: "keyword", values: ["goto"] },
          { token: "operator", values: [":"], optional: true }
        ],
        true
      )
    )
      return null;

    let value = context.reader.read();
    while (!context.reader.isEOF() && !/[\W]/.test(context.reader.peek()))
      value += context.reader.read();

    return context.createToken("label", value);
  }
476240
private void examineBasicBlocks() throws DataflowAnalysisException, CFGBuilderException {
        // Look for null check blocks where the reference being checked
        // is definitely null, or null on some path
        Iterator<BasicBlock> bbIter = invDataflow.getCFG().blockIterator();
        while (bbIter.hasNext()) {
            BasicBlock basicBlock = bbIter.next();

            if (basicBlock.isNullCheck()) {
                analyzeNullCheck(invDataflow, basicBlock);
            } else if (!basicBlock.isEmpty()) {
                // Look for all reference comparisons where
                // - both values compared are definitely null, or
                // - one value is definitely null and one is definitely not null
                // These cases are not null dereferences,
                // but they are quite likely to indicate an error, so while
                // we've got
                // information about null values, we may as well report them.
                InstructionHandle lastHandle = basicBlock.getLastInstruction();
                Instruction last = lastHandle.getInstruction();
                switch (last.getOpcode()) {
                case Const.IF_ACMPEQ:
                case Const.IF_ACMPNE:
                    analyzeRefComparisonBranch(basicBlock, lastHandle);
                    break;
                case Const.IFNULL:
                case Const.IFNONNULL:
                    analyzeIfNullBranch(basicBlock, lastHandle);
                    break;
                default:
                    break;
                }
            }
        }
    }
708473
JCBlock block(int pos, long flags) {
        accept(LBRACE);
        List<JCStatement> stats = blockStatements();
        JCBlock t = F.at(pos).Block(flags, stats);
        while (token.kind == CASE || token.kind == DEFAULT) {
            syntaxError("orphaned", token.kind);
            switchBlockStatementGroups();
        }
        // the Block node has a field "endpos" for first char of last token, which is
        // usually but not necessarily the last char of the last token.
        t.endpos = token.pos;
        accept(RBRACE);
        return toP(t);
    }
1107079
void calcNullable(RBBINode n) {
           if (n == null) {
               return;
           }
           if (n.fType == RBBINode.setRef ||
               n.fType == RBBINode.endMark ) {
               // These are non-empty leaf node types.
               n.fNullable = false;
               return;
           }

           if (n.fType == RBBINode.lookAhead || n.fType == RBBINode.tag) {
               // Lookahead marker node.  It's a leaf, so no recursion on children.
               // It's nullable because it does not match any literal text from the input stream.
               n.fNullable = true;
               return;
           }


           // The node is not a leaf.
           //  Calculate nullable on its children.
           calcNullable(n.fLeftChild);
           calcNullable(n.fRightChild);

           // Apply functions from table 3.40 in Aho
           if (n.fType == RBBINode.opOr) {
               n.fNullable = n.fLeftChild.fNullable || n.fRightChild.fNullable;
           }
           else if (n.fType == RBBINode.opCat) {
               n.fNullable = n.fLeftChild.fNullable && n.fRightChild.fNullable;
           }
           else if (n.fType == RBBINode.opStar || n.fType == RBBINode.opQuestion) {
               n.fNullable = true;
           }
           else {
               n.fNullable = false;
           }
       }
820546
def _typed_null_handler(c, ctx):
    """"""
    assert c == _DOT
    c, self = yield
    nxt = _NULL_STARTS
    i = 0
    length = None
    done = False
    trans = ctx.immediate_transition(self)
    while True:
        if done:
            if _ends_value(c) or (ctx.container.ion_type is IonType.SEXP and c in _OPERATORS):
                trans = ctx.event_transition(IonEvent, IonEventType.SCALAR, nxt.ion_type, None)
            else:
                _illegal_character(c, ctx, 'Illegal null type.')
        elif length is None:
            if c not in nxt:
                _illegal_character(c, ctx, 'Illegal null type.')
            nxt = nxt[c]
            if isinstance(nxt, _NullSequence):
                length = len(nxt.sequence)
        else:
            if c != nxt[i]:
                _illegal_character(c, ctx, 'Illegal null type.')
            i += 1
            done = i == length
        c, _ = yield trans
1128634
def index_of_lowest_precedence(operators,associativity=:left)
    lowest = lowest_precedence = nil
    operators.each_with_index do |operator,i|
      operator_string = operator.to_s
      precedence = operator_precedence(operator_string)
      right_associative = @right_operators_regexp && operator_string[@right_operators_regexp]
      if !lowest || (right_associative ? precedence < lowest_precedence : precedence <= lowest_precedence)
        lowest = i
        lowest_precedence = precedence
      end
    end
    lowest
  end
516216
protected Expression power() {
        Expression left = atom();
        if (tokenizer.current().isSymbol("^") || tokenizer.current().isSymbol("**")) {
            tokenizer.consume();
            Expression right = power();
            return reOrder(left, right, BinaryOperation.Op.POWER);
        }
        return left;
    }
915309
function(a, b)
{
   var rval = 0;
   
   /*
   3. For each property, compare sorted object values.
   3.1. The bnode with fewer objects is first.
   3.2. For each object value, compare only literals and non-bnodes.
   3.2.1. The bnode with fewer non-bnodes is first.
   3.2.2. The bnode with a string object is first.
   3.2.3. The bnode with the alphabetically-first string is first.
   3.2.4. The bnode with a @literal is first.
   3.2.5. The bnode with the alphabetically-first @literal is first.
   3.2.6. The bnode with the alphabetically-first @type is first.
   3.2.7. The bnode with a @language is first.
   3.2.8. The bnode with the alphabetically-first @language is first.
   3.2.9. The bnode with the alphabetically-first @id is first.
   */
   
   for(var p in a)
   {
      // skip IDs (IRIs)
      if(p !== '@id')
      {
         // step #3.1
         var lenA = (a[p].constructor === Array) ? a[p].length : 1;
         var lenB = (b[p].constructor === Array) ? b[p].length : 1;
         rval = _compare(lenA, lenB);

         // step #3.2.1
         if(rval === 0)
         {
            // normalize objects to an array
            var objsA = a[p];
            var objsB = b[p];
            if(objsA.constructor !== Array)
            {
               objsA = [objsA];
               objsB = [objsB];
            }
            
            // compare non-bnodes (remove bnodes from comparison)
            objsA = objsA.filter(function(e) {return !_isNamedBlankNode(e);});
            objsB = objsB.filter(function(e) {return !_isNamedBlankNode(e);});
            rval = _compare(objsA.length, objsB.length);
         }
         
         // steps #3.2.2-3.2.9
         if(rval === 0)
         {
            objsA.sort(_compareObjects);
            objsB.sort(_compareObjects);
            for(var i = 0; i < objsA.length && rval === 0; ++i)
            {
               rval = _compareObjects(objsA[i], objsB[i]);
            }
         }
         
         if(rval !== 0)
         {
            break;
         }
      }
   }
   
   return rval;
}
217733
@Override
    protected String naryOperator(final NAryOperator operator, final String opString) {
        final List<Formula> operands = new ArrayList<>();
        for (final Formula op : operator) {
            operands.add(op);
        }
        final int size = operator.numberOfOperands();
        Collections.sort(operands, this.comparator);
        final StringBuilder sb = new StringBuilder();
        int count = 0;
        Formula last = null;
        for (final Formula op : operands) {
            if (++count == size) {
                last = op;
            } else {
                sb.append(operator.type().precedence() < op.type().precedence() ? toString(op) : bracket(op));
                sb.append(opString);
            }
        }
        if (last != null) {
            sb.append(operator.type().precedence() < last.type().precedence() ? toString(last) : bracket(last));
        }
        return sb.toString();
    }