Select .d inside .c that is adjacent to .b inside .a
Yes, that's right. The way you placed your brackets also makes sense to me. Nest them some more to be clearer:
(((.a) .b) + .c) .d
In this example, only the second p.d element is matched:
<div class="a">
  <div class="b">
    <p class="d"></p> <!-- [1] -->
  </div>
  <div class="c">
    <p class="d"></p> <!-- [2] -->
  </div> 
  <div class="c">
    <p class="d"></p> <!-- [3] -->
  </div>
</div>
- Not selected
 This- p.delement isn't contained in an element with the class- c.
 
- Selected
 This- p.delement is contained in a- .celement. The- .celement immediately follows a- .belement, and both of these share the- .aancestor element.
 
- Not selected
 This- p.delement is contained in a- .celement. However, this doesn't immediately follow a- .belement; instead it comes after another- .celement, so its- p.ddoesn't satisfy the selector.
 - If the general sibling combinator - ~were used instead of the adjacent sibling combinator- +, as in
 - .a .b ~ .c .d
 - Then this - p.dwould be matched.
 
What is the operator + precedence in CSS grammar?
All compound selectors and combinators in a sequence are processed from right to left, using each selector group as a step. This answer elaborates. (This may be counter-intuitive when you think in brackets; to make sense of it simply treat the brackets as if the outermost ones came first. Either ordering is fine, though, as long as you remember that combinators aren't associative. See the linked answer for details.)