docs: private String expandLHS(final String lhs,
                               int lineOffset) {
          substitutions = new ArrayList<Map<String, String>>();
  
          //        logger.info( "*** LHS>" + lhs + "<" );
          final StringBuilder buf = new StringBuilder();
          
          final String[] lines = lhs.split( (lhs.indexOf("\r\n") >= 0 ? "\r\n":"\n"),
                                            -1 ); // since we assembled the string, we know line breaks are \n
          final String[] expanded = new String[lines.length]; // buffer for expanded lines
          int lastExpanded = -1;
          int lastPattern = -1;
          for ( int i = 0; i < lines.length - 1; i++ ) {
              final String trimmed = lines[i].trim();
              expanded[++lastExpanded] = lines[i];
  
              if ( trimmed.length() == 0 || trimmed.startsWith( "#" ) || trimmed.startsWith( "//" ) ) {
                  // comments - do nothing
              } else if ( trimmed.startsWith( ">" ) ) {
                  // passthrough code - simply remove the passthrough mark character
                  expanded[lastExpanded] = lines[i].replaceFirst( ">",
                                                                  " " );
                  lastPattern = lastExpanded;
              } else {
                  // regular expansion - expand the expression
                  expanded[lastExpanded] =
                          substitute( expanded[lastExpanded],
                                      this.condition,
                                      i + lineOffset,
                                      useWhen,
                                      showSteps );
  
                  // do we need to report errors for that?
                  if ( lines[i].equals( expanded[lastExpanded] ) ) {
                      // report error
                      this.addError( new ExpanderException( "Unable to expand: " + lines[i].replaceAll( "[\n\r]",
                                                                                                        "" ).trim(),
                                                            i + lineOffset ) );
                  }
                  // but if the original starts with a "-", it means we need to add it
                  // as a constraint to the previous pattern
                  if ( trimmed.startsWith( "-" ) && (!lines[i].equals( expanded[lastExpanded] )) ) {
                      if ( lastPattern >= 0 ) {
                          ConstraintInformation c = ConstraintInformation.findConstraintInformationInPattern( expanded[lastPattern] );
                          if ( c.start > -1 ) {
                              // rebuilding previous pattern structure
                              expanded[lastPattern] = expanded[lastPattern].substring( 0,
                                                                                       c.start ) + c.constraints + ((c.constraints.trim().length() == 0) ? "" : ", ") + expanded[lastExpanded].trim() + expanded[lastPattern].substring( c.end );
                          } else {
                              // error, pattern not found to add constraint to
                              this.addError( new ExpanderException( "No pattern was found to add the constraint to: " + lines[i].trim(),
                                                                    i + lineOffset ) );
                          }
                      }
                      lastExpanded--;
                  } else {
                      lastPattern = lastExpanded;
                  }
              }
          }
          for ( int i = 0; i <= lastExpanded; i++ ) {
              buf.append( expanded[i] );
              buf.append( nl );
          }
  
          return buf.toString();
      }