code: protected void parse(Reader reader) throws FSMParseException, IOException {
          Part part = Part.DataDefinition;
          partLineNumber = 0;
  
          final StreamTokenizer streamTokenizer = getStreamTokenizer(reader);
  
          while (streamTokenizer.nextToken() != StreamTokenizer.TT_EOF) {
              streamTokenizer.pushBack();
              switch (part) {
                  case DataDefinition: {
                      if (streamTokenizer.nextToken() == StreamTokenizer.TT_WORD && "---".equals(streamTokenizer.sval)) {
                          // we entered the part with the state vectors
                          part = Part.StateVectors;
                          partLineNumber = 0;
                          checkDataDefinitions(streamTokenizer);
                      } else {
                          streamTokenizer.pushBack();
                          parseDataDefinition(streamTokenizer);
                      }
                      break;
                  }
                  case StateVectors: {
                      if (streamTokenizer.nextToken() == StreamTokenizer.TT_WORD && "---".equals(streamTokenizer.sval)) {
                          // we entered the part with the transitions.
                          part = Part.Transitions;
                          partLineNumber = 0;
                          checkStateVectors(streamTokenizer);
                      } else {
                          streamTokenizer.pushBack();
                          parseStateVector(streamTokenizer);
                      }
                      break;
                  }
                  case Transitions: {
                      parseTransition(streamTokenizer);
                      break;
                  }
                  default: throw new AssertionError();
              }
              // consume all tokens until EOL is reached
              while (streamTokenizer.nextToken() != StreamTokenizer.TT_EOL) {}
              partLineNumber++;
          }
          checkTransitions(streamTokenizer);
          reader.close();
      }
docs: Parsed the FSM file line-by-line.
  At first this method expects to parse data definitions, and calls {@link #parseDataDefinition(StreamTokenizer)}
  for each data definition. After "---" is encountered {@link #checkDataDefinitions(StreamTokenizer)} is called,
  and this method expects to parse state vectors. The behavior is similar for state vectors and transitions.
  For each line this method will increment {@link #partLineNumber}, and reset it when a new part in the FSM file
  begins.
  
  Note that {@link StreamTokenizer} allows one to push back tokens. This is used whenever we have checked type
  type of token we are going to read.
  
  @param reader
  the source of the FSM file
  
  @throws FSMParseException when the FSM source is invalid.
  @throws IOException when FSM source could not be read.