protected virtual void Parse(IList <IToken> tokens, INotation notation, BeatType beatType, InstrumentType instrumentType)
        {
            notation.Repeating      = DetectRepeating(tokens);
            notation.BeatType       = beatType;
            notation.InstrumentType = instrumentType;

            var       tokenIndex   = 0;
            var       measureIndex = -1;
            var       lineIndex    = 0;
            var       beatIndex    = 0;
            var       noteIndex    = 0f;
            TokenType?flamStart    = null;

            IMeasure[] measures = null;

            var tokensToParse = tokens.ToList();

            while (tokensToParse.Any())
            {
                var token = tokensToParse.First();
                tokensToParse.RemoveAt(0);

                switch (token.TokenType)
                {
                case TokenType.MeasureLine:
                    beatIndex = 0;
                    noteIndex = 0;

                    if (!tokensToParse.Any() || tokensToParse.First().TokenType == TokenType.NextBeatNewLine || tokensToParse.First().TokenType == TokenType.End)
                    {
                        break;
                    }

                    measureIndex++;
                    notation.AddMeasure();
                    measures = notation.Measures;
                    break;

                case TokenType.NextBeat:
                    beatIndex++;
                    noteIndex = 0;
                    break;

                case TokenType.NextBeatHalf:
                    if (noteIndex % .5f == 0f)
                    {
                        beatIndex++;
                        noteIndex = 0f;
                    }
                    else
                    {
                        noteIndex += .5f;
                    }
                    break;

                case TokenType.NextBeatTwoThird:
                    if (noteIndex % .6667f == 0f)
                    {
                        beatIndex++;
                        noteIndex = 0f;
                    }
                    else
                    {
                        noteIndex += .6667f;
                    }
                    break;

                case TokenType.NextBeatNewLine:
                    lineIndex++;
                    beatIndex = 0;
                    noteIndex = 0;
                    break;

                case TokenType.OpenBassFlam:
                case TokenType.OpenToneFlam:
                case TokenType.OpenSlapFlam:
                    EnsureMeasures(notation.Name, measures, tokenIndex, token);
                    flamStart = token.TokenType;
                    break;

                case TokenType.OpenBass:
                case TokenType.OpenBassSmall:
                case TokenType.OpenTone:
                case TokenType.OpenToneSmall:
                case TokenType.OpenSlap:
                case TokenType.OpenSlapSmall:
                    EnsureMeasures(notation.Name, measures, tokenIndex, token);
                    if (flamStart != null)
                    {
                        measures[measureIndex].Beats[beatIndex].AddSound(noteIndex, TokenToSound(instrumentType, flamStart.Value));
                        measures[measureIndex].Beats[beatIndex].AddSound(noteIndex, TokenToSound(instrumentType, token.TokenType), .05f);
                        flamStart = null;
                    }
                    else
                    {
                        measures[measureIndex].Beats[beatIndex].AddSound(noteIndex, TokenToSound(instrumentType, token.TokenType));
                    }

                    break;

                case TokenType.DounBell:
                    measures[measureIndex].Beats[beatIndex].AddSound(noteIndex, TokenToSound(instrumentType, token.TokenType));
                    break;

                case TokenType.ConnectionLine:
                    noteIndex++;
                    break;

                case TokenType.ConnectionLineHalf:
                case TokenType.DoubleConnectionLineHalf:
                    noteIndex += .5f;
                    break;

                case TokenType.ConnectionLineTwoThird:
                case TokenType.DoubleConnectionLineTwoThird:
                    noteIndex += .6667f;
                    break;
                }

                if (notation.BeatType != BeatType.Unknown && noteIndex > notation.NotesPerBeat * 2)
                {
                    noteIndex = 0f;
                    beatIndex++;
                }

                tokenIndex++;
            }
        }