code: Rule Voice() {
  		return Sequence(
  			ALPHASandDIGITS().label("VoiceNumber"),
  			ZeroOrMoreS(
  				SequenceS(suppr(WSPS()),
  					FirstOfS(VoiceName(), VoiceSubname(),
  						VoiceTranspose(), VoiceMerge(),
  						VoiceStems(), VoiceStaves(),
  						VoiceBracket(), ClefMiddle(),
  						/* clef */
  						//V: RH1 clef=treble name="Piano"
  						//if Clef() instead of its definition,
  						//will try to parse name="Piano" as ClefName
  						//but it's VoiceName
  						SequenceS(FirstOfS(
  									ClefName(),
  									SequenceS(IgnoreCase("clef="),
  											FirstOfS(ClefNote(), ClefName()))
  									),
  								OptionalS(ClefLine()),
  								OptionalS(SequenceS(Optional(WSPS()).suppressNode(), ClefOctave()))),
  						ClefMiddle(),
  						ClefStafflines(),
  						ClefTranspose(),
  						/* end clef */
  						OneOrMore(VCHAR())
  									.label(VoiceOther).suppressSubnodes()
  						)
  				)
  			)
  		).label(Voice);
  	}
docs: maybe "stems=up" / "stems=down" / "stems=normal" instead?
  
  voice ::= 1*(ALPHA / DIGIT) *(1*WSP (clef / voice-name / voice-subname / voice-transpose / "merge" / "up" / "down"))