public boolean parseMemberExpression(boolean isTargetExpression) {
    // in sequence a.b.... .c all members but last are always references, and the last may be target.
    boolean recastFirstIdentifier = false;
    boolean recastQualifier = false;
    do {
      boolean firstIdentifierIsTarget = isTargetExpression && !recastFirstIdentifier;
      SyntaxTreeBuilder.Marker expr = myBuilder.mark();
      if (!parsePrimaryExpression(firstIdentifierIsTarget)) {
        expr.drop();
        return false;
      }

      while (true) {
        final IElementType tokenType = myBuilder.getTokenType();
        if (tokenType == PyTokenTypes.DOT) {
          if (firstIdentifierIsTarget) {
            recastFirstIdentifier = true;
            expr.rollbackTo();
            break;
          }
          myBuilder.advanceLexer();
          checkMatches(PyTokenTypes.IDENTIFIER, message("PARSE.expected.name"));
          if (isTargetExpression && !recastQualifier && !atAnyOfTokens(PyTokenTypes.DOT, PyTokenTypes.LPAR, PyTokenTypes.LBRACKET)) {
            expr.done(PyElementTypes.TARGET_EXPRESSION);
          }
          else {
            expr.done(getReferenceType());
          }
          expr = expr.precede();
        }
        else if (tokenType == PyTokenTypes.LPAR) {
          parseArgumentList();
          expr.done(PyElementTypes.CALL_EXPRESSION);
          expr = expr.precede();
        }
        else if (tokenType == PyTokenTypes.LBRACKET) {
          myBuilder.advanceLexer();
          parseSliceOrSubscriptionExpression(expr, false);
          if (isTargetExpression && !recastQualifier) {
            recastFirstIdentifier = true; // subscription is always a reference
            recastQualifier = true; // recast non-first qualifiers too
            expr.rollbackTo();
            break;
          }
          expr = expr.precede();
        }
        else {
          expr.drop();
          break;
        }
        recastFirstIdentifier = false; // it is true only after a break; normal flow always unsets it.
        // recastQualifier is untouched, it remembers whether qualifiers were already recast
      }
    }
    while (recastFirstIdentifier);

    return true;
  }
public boolean parseMemberExpression(boolean isTargetExpression)