Example #1
0
  /**
   * Parses the ABCHeader information as prescribed by the ABC Grammar subset understood by the
   * ABCParser
   */
  private void parseHeader() {
    // All the components of a valid ABCMusic
    List<Voice> VoicesList = new ArrayList<Voice>();

    String name, title, IDNum;
    int bpm;
    int[] meterSum = new int[2];
    int[] noteLength = new int[2];
    NoteToken key;

    // Booleans for having set the optional quantities
    boolean setL = Boolean.FALSE;
    boolean setM = Boolean.FALSE;
    boolean setQ = Boolean.FALSE;
    boolean setC = Boolean.FALSE;

    // Establish Defaults for unnecessary fields so that we only need to add
    // the the vars

    bpm = 100;
    noteLength[0] = 1;
    noteLength[1] = 8;
    meterSum[0] = 4;
    meterSum[1] = 4;
    name = "Unknown";

    // Now grab X and T since they are in a manditory order
    IDNum = lexer.getNextElemToken().getText();
    checkAndTrashEoL();
    next = lexer.GetNextTokenType();
    if (next == Tokens.Type.FIELD_TITLE) {
      title = lexer.getNextElemToken().getText();
    } else {
      throw new IllegalArgumentException("Expected a music Title, received: " + next);
    }
    checkAndTrashEoL();
    // Until you encounter the Field Key, look for all optional classes, and only allow them to be
    // set once
    while (next != Tokens.Type.FIELD_KEY) {
      next = lexer.GetNextTokenType();
      switch (next) {
        case FIELD_DEFAULT_LENGTH:
          if (!setL) {
            ElemToken tempToken = lexer.getNextElemToken();
            int[] settingArray = tempToken.getVals();
            noteLength[0] = settingArray[0];
            noteLength[1] = settingArray[1];
            setL = Boolean.TRUE;
          } else {
            throw new IllegalArgumentException("Cannot Set Default Length more than once");
          }

          checkAndTrashEoL();
          break;
        case FIELD_METER:
          if (!setM) {
            ElemToken tempToken = lexer.getNextElemToken();
            int[] settingArray = tempToken.getVals();
            meterSum[0] = settingArray[0];
            meterSum[1] = settingArray[1];
            setM = Boolean.TRUE;
          } else {
            throw new IllegalArgumentException("Cannot Set Meter Length more than once");
          }

          checkAndTrashEoL();
          break;

        case FIELD_TEMPO:
          if (!setQ) {
            ElemToken tempToken = lexer.getNextElemToken();
            int[] settingArray = tempToken.getVals();
            bpm = settingArray[0];
            setQ = Boolean.TRUE;
          } else {
            throw new IllegalArgumentException("Cannot Set Tempo more than once");
          }
          checkAndTrashEoL();
          break;

        case FIELD_COMPOSER:
          if (!setC) {
            ElemToken tempToken = lexer.getNextElemToken();
            name = tempToken.getText();
            setC = Boolean.TRUE;
          } else {
            throw new IllegalArgumentException("Cannot Set Composer more than once");
          }

          checkAndTrashEoL();
          break;

        case FIELD_VOICE:
          VoicesList.add(new Voice(lexer.getNextElemToken().getText()));
          checkAndTrashEoL();
          break;

        default:
          break;
      }
    }
    // Last element should be the field key
    if (next == Tokens.Type.FIELD_KEY) {
      key = lexer.getNextElemToken().getKey();
    } else {
      throw new IllegalArgumentException("Expected a music Key for the piece, received: " + next);
    }
    checkAndTrashEoL();
    // If the file has no voices, then we need at least one for the ABCMusic file to be valid
    // Construct a dummy one
    if (VoicesList.size() == 0) {
      VoicesList.add(new Voice("DummyVoice"));
    }
    // Initialize the new ABCMusic file
    ThePiece = new ABCMusic(VoicesList, name, key, noteLength, meterSum, bpm, title, IDNum);
  }
Example #2
0
 /**
  * Parses a given set of Meters in a given Voice until an EoL character is found utilizes a list
  * of mutable, working meters to manage repeats
  *
  * <p>Note: Highly dependent on proper use of copying references to a list versus copying the
  * actual list so edit carefully
  *
  * <p>Note: Assumes that nested repeats do not exist, however they are musically unsound so the
  * assumption seems valid
  */
 private void parseBar() {
   Bars workingBar;
   // If we havent used the voice, initialie its repeatList, else get its repeat list
   if (repeatTracker.size() < (workingIndex + 1)) {
     workingBar = new Bars();
     repeatTracker.add(workingBar);
   } else {
     workingBar = repeatTracker.get(workingIndex);
   }
   // Construct our working meter and recursively get it
   Meters workingMeter;
   while (next != Tokens.Type.END_OF_LINE && next != Tokens.Type.COMMENT) {
     workingMeter = parseMeter();
     workingBar.addElts(workingMeter);
     next = lexer.GetNextTokenType();
     // If we find an end of meter
     if (next == Tokens.Type.BARLINE) {
       ElemToken barToken = lexer.getNextElemToken();
       switch (barToken.getVals()[0]) {
         case 1:
           // Do nothing for regular meters
           break;
         case 3:
           // Add all marked for repeat meters to the voice for repeats
           workingVoice.addCopyElts(workingBar);
           break;
         default:
           // Add all unadded meters and clear what gets repeated otherwise
           workingVoice.addCopyElts(workingBar);
           workingBar.clear();
           break;
       }
       next = lexer.GetNextTokenType();
       // If we find a # Repeat token
     } else if (next == Tokens.Type.REPEAT) {
       int repeatNum = lexer.getNextElemToken().getVals()[0];
       // Only for the first repeat token
       if (repeatNum == 1) {
         // Temporarily store the contents to be repeated
         Bars tempBar = new Bars();
         for (Iterator<Meters> i = workingBar.MetersList.iterator(); i.hasNext(); ) {
           tempBar.addCopyElts(i.next());
         }
         // Recursively parse to the Repeat Barline char, which will add the meters
         // Then clear the list and re-add everything we stored before getting the
         // First repeat information
         parseBar();
         workingBar.clear();
         for (Iterator<Meters> i = tempBar.MetersList.iterator(); i.hasNext(); ) {
           workingBar.addCopyElts(i.next());
         }
         // Now get the second repeat information
         parseBar();
       } else {
         // Just break the given nested parse for second repeats, they are
         // handled by Barline characters that end them
         break;
       }
       next = lexer.GetNextTokenType();
     } else if (next == Tokens.Type.END_OF_LINE || next == Tokens.Type.COMMENT) {
       break;
     } else {
       throw new IllegalArgumentException("Expected a bar to have a termination, got: " + next);
     }
   }
 }