Esempio n. 1
0
 /**
  * Parses the given .abc File into an ADT, throws RuntimeExceptions upon encountering ABC Grammar
  * breaking constructs
  *
  * <p>Note: allows a near indefinite break between the end of the Key signature and the start of
  * music, this break can contain comments, but once the music starts, it must adhere to the
  * grammar
  *
  * @return An ABCMusic file which contains all the methods necessary to both play and analyze the
  *     .abc file contained by the ABCParser
  */
 public ABCMusic parse() {
   next = lexer.GetNextTokenType();
   if (next == Tokens.Type.FIELD_NUMBER) {
     parseHeader();
     next = lexer.GetNextTokenType();
     while (next == Tokens.Type.END_OF_LINE) {
       checkAndTrashEoL();
       next = lexer.GetNextTokenType();
     }
     if (!(next == Tokens.Type.FIELD_VOICE
         || next == Tokens.Type.COMMENT
         || next == Tokens.Type.NOTE
         || next == Tokens.Type.CHORD
         || next == Tokens.Type.TUPLET
         || next == Tokens.Type.REST)) {
       throw new IllegalArgumentException("Expected start of music instead got: " + next);
     }
     parseMusic();
     next = lexer.GetNextTokenType();
     if (next != Tokens.Type.END_OF_LINE) {
       throw new IllegalArgumentException(
           "Expected music to be over, instead there was a: " + next);
     }
   } else {
     throw new IllegalArgumentException("Expected a music ID, received: " + next);
   }
   return ThePiece;
 }
Esempio n. 2
0
 /**
  * Verifies an EoL Character terminates any given line for which it is run, as well as Checking
  * for Comment blocks and discarding them (since they are part of an EoL)
  *
  * <p>Note: Assumes that comments are unused or needed, and thus they will never be printed to
  * screen
  */
 private void checkAndTrashEoL() {
   next = lexer.GetNextTokenType();
   if (next == Tokens.Type.END_OF_LINE) {
     // Little dirty discard of EoL characters
     @SuppressWarnings("unused")
     Tokens dummy = lexer.getEndOfLineToken();
   } else if (next == Tokens.Type.COMMENT) {
     // Little dirty discard of Comments, they dont matter i think?
     // Otherwise this is where Comments would be set to print out
     @SuppressWarnings("unused")
     Tokens dummy = lexer.getNextElemToken();
     checkAndTrashEoL();
   } else {
     throw new IllegalArgumentException("Expected a EoL, received: " + next);
   }
 }
Esempio n. 3
0
 /**
  * Parses the ABCMusic information as prescribed by the ABC Grammar understood by the ABCParser,
  * does so recursively via sub-functions and stores the information in the ABCMusic output file's
  * VoicesList
  */
 private void parseMusic() {
   workingIndex = 0;
   workingVoice = ThePiece.VoicesList.get(0);
   // Until we are out of Music
   while (!lexer.IsDone()) {
     next = lexer.GetNextTokenType();
     if (next == Tokens.Type.END_OF_LINE || next == Tokens.Type.COMMENT) {
       // Trash found comments and EoL chars
       checkAndTrashEoL();
     } else if (next == Tokens.Type.FIELD_VOICE) {
       String nextVoice = lexer.getNextElemToken().getText();
       int index = 0;
       // Try all the voices to see what we should switch to
       for (Iterator<Voice> i = ThePiece.VoicesList.iterator(); i.hasNext(); ) {
         if (i.next().getName().equals(nextVoice)) {
           workingVoice = ThePiece.VoicesList.get(index);
           workingIndex = index;
         } else {
           index++;
           // If we have tried all Voices, then it must not exist
           if (index >= ThePiece.VoicesList.size()) {
             throw new IllegalArgumentException(
                 "Invalid Voice name in the Music Section: " + nextVoice);
           }
         }
       }
     } else {
       // Recurse on a given Voice to parse it
       parseBar();
     }
   }
   // When we reach the end, all remaining meters to all Voices to finalize the piece
   for (int index = 0; index < ThePiece.VoicesList.size(); index++) {
     workingVoice = ThePiece.VoicesList.get(index);
     workingIndex = index;
     workingVoice.addCopyElts(repeatTracker.get(workingIndex));
   }
 }
Esempio n. 4
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);
  }