I think this post of mine should answer your question. The super short summary is: you can use buildPartialBlock, and include marker types in the partial results to turn the builder into a state machine where possible state transitions are defined by buildPartialBlock overloads.