function expression(context, rbp) {
    var left, isArray = false, isObject = false;
    var initial = context & prodParams.initial;
    var curr;

    context &= ~prodParams.initial;

    state.nameStack.push();

    if (state.tokens.next.id === "(end)")
      error("E006", state.tokens.curr);

    advance();

    if (initial) {
      state.funct["(verb)"] = state.tokens.curr.value;
      state.tokens.curr.beginsStmt = true;
    }

    curr = state.tokens.curr;

    if (initial && curr.fud && (!curr.useFud || curr.useFud(context))) {
      left = state.tokens.curr.fud(context);
    } else {
      if (state.tokens.curr.nud) {
        left = state.tokens.curr.nud(context, rbp);
      } else {
        error("E030", state.tokens.curr, state.tokens.curr.id);
      }

      while (rbp < state.tokens.next.lbp && !isEndOfExpr(context)) {
        isArray = state.tokens.curr.value === "Array";
        isObject = state.tokens.curr.value === "Object";

        // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
        // Line breaks in IfStatement heads exist to satisfy the checkJSHint
        // "Line too long." error.
        if (left && (left.value || (left.first && left.first.value))) {
          // If the left.value is not "new", or the left.first.value is a "."
          // then safely assume that this is not "new Array()" and possibly
          // not "new Object()"...
          if (left.value !== "new" ||
            (left.first && left.first.value && left.first.value === ".")) {
            isArray = false;
            // ...In the case of Object, if the left.value and state.tokens.curr.value
            // are not equal, then safely assume that this not "new Object()"
            if (left.value !== state.tokens.curr.value) {
              isObject = false;
            }
          }
        }

        advance();

        if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
          warning("W009", state.tokens.curr);
        }

        if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
          warning("W010", state.tokens.curr);
        }

        if (left && state.tokens.curr.led) {
          left = state.tokens.curr.led(context, left);
        } else {
          error("E033", state.tokens.curr, state.tokens.curr.id);
        }
      }
    }

    state.nameStack.pop();

    return left;
  }
The `expression` function is the heart of JSHint's parsing behaior. It is
based on the Pratt parser, but it extends that model with a `fud` method.
Short for "first null denotation," it it similar to the `nud` ("null
denotation") function, but it is only used on the first token of a
statement. This simplifies usage in statement-oriented languages like
JavaScript.

.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.

In addition to parsing, this function applies a number of linting patterns.

@param {number} context - the parsing context (a bitfield describing
                          conditions of the current parsing operation
                          which can influence how the next tokens are
                          interpreted); see `prod-params.js` for more
                          detail)
@param {number} rbp - the right-binding power of the token to be consumed