public String format(ELEMENT grammarElement, boolean needParenthesis) {
   TOKEN token = adapter.getToken(grammarElement);
   if (token != null) {
     String cardinality = getCardinality(grammarElement);
     if (cardinality == null) return tokenToString.apply(token);
     return tokenToString.apply(token) + cardinality;
   }
   Iterable<ELEMENT> alternative = adapter.getAlternativeChildren(grammarElement);
   if (alternative != null)
     return format(grammarElement, alternative, " | ", false, needParenthesis, 5);
   Iterable<ELEMENT> group = adapter.getSequentialChildren(grammarElement);
   if (group != null) return format(grammarElement, group, " ", false, needParenthesis, 5);
   Iterable<ELEMENT> ungroup = adapter.getUnorderedChildren(grammarElement);
   if (ungroup != null) return format(grammarElement, ungroup, " & ", false, needParenthesis, 5);
   return "<unknown>";
 }
 protected String getCardinality(ELEMENT ele) {
   return adapter.isMany(ele)
       ? adapter.isOptional(ele) ? "*" : "+"
       : adapter.isOptional(ele) ? "?" : null;
 }