Exemplo n.º 1
0
        public override bool TryParse(Scanner scanner, out ChordFingeringNode result)
        {
            result = new ChordFingeringNode();
            var anchor                       = scanner.MakeAnchor();
            var remainingLine                = scanner.RemainingLine.Trim();
            var containsDelimiter            = remainingLine.Any(char.IsWhiteSpace);
            var containsFingerIndexSpecifier = remainingLine.Any(c => c == '<' || c == '>');
            var isShortForm                  = !containsDelimiter && !containsFingerIndexSpecifier;

            while (!_terminatorPredicate(scanner))
            {
                var noteAnchor = scanner.MakeAnchor();

                var str = isShortForm ? scanner.ReadPattern(@"[\dxX\-]") : scanner.ReadAnyPatternOf(@"\d+", @"[xX\-]");

                if (string.IsNullOrEmpty(str))
                {
                    this.Report(LogLevel.Warning, scanner.LastReadRange,
                                Messages.Error_ChordFingeringInvalidFingering);
                    result = null;
                    return(false);
                }

                switch (str)
                {
                case "x":
                case "X":
                case "-":
                {
                    var fret = new LiteralNode <int>(Chord.FingeringSkipString, scanner.LastReadRange);
                    result.Fingerings.Add(new ChordFingeringNoteNode {
                            Fret = fret, Range = scanner.LastReadRange
                        });
                    break;
                }

                default:
                    int fretNumber;
                    if (!int.TryParse(str, out fretNumber))     // todo: prevent too large fret number
                    {
                        this.Report(LogLevel.Warning, scanner.LastReadRange,
                                    Messages.Error_ChordFingeringInvalidFingering);
                        result = null;
                        return(false);
                    }

                    if (fretNumber > 24)
                    {
                        this.Report(LogLevel.Warning, scanner.LastReadRange,
                                    Messages.Warning_ChordFingeringFretTooHigh);
                    }

                    var note = new ChordFingeringNoteNode
                    {
                        Fret  = new LiteralNode <int>(fretNumber, scanner.LastReadRange),
                        Range = scanner.LastReadRange
                    };

                    if (fretNumber != 0)
                    {
                        scanner.SkipWhitespaces();
                        if (scanner.Expect('<'))
                        {
                            scanner.SkipWhitespaces();

                            var fingerIndexString = scanner.ReadPattern(@"[\dtT]");
                            if (string.IsNullOrEmpty(fingerIndexString))
                            {
                                this.Report(LogLevel.Error, scanner.Pointer.AsRange(),
                                            Messages.Error_ChordFingerIndexExpected);
                                return(false);
                            }


                            LeftHandFingerIndex fingerIndex;
                            switch (fingerIndexString)
                            {
                            case "t":
                            case "T":
                                fingerIndex = LeftHandFingerIndex.Thumb; break;

                            case "1":
                                fingerIndex = LeftHandFingerIndex.Index; break;

                            case "2":
                                fingerIndex = LeftHandFingerIndex.Middle; break;

                            case "3":
                                fingerIndex = LeftHandFingerIndex.Ring; break;

                            case "4":
                                fingerIndex = LeftHandFingerIndex.Pinky; break;

                            default:
                                this.Report(LogLevel.Error, scanner.LastReadRange,
                                            Messages.Error_UnrecognizableFingerIndex);
                                return(false);
                            }


                            note.FingerIndex = new LiteralNode <LeftHandFingerIndex>(fingerIndex,
                                                                                     scanner.LastReadRange);

                            scanner.SkipWhitespaces();

                            ExistencyNode importancy;
                            if (new CharExistencyParser('!').TryParse(scanner, out importancy))
                            {
                                note.Importancy = importancy;
                                scanner.SkipWhitespaces();
                            }

                            if (!scanner.Expect('>'))
                            {
                                this.Report(LogLevel.Error, scanner.Pointer.AsRange(),
                                            Messages.Error_ChordFingerIndexNotEnclosed);
                                return(false);
                            }
                        }
                    }

                    note.Range = noteAnchor.Range;
                    result.Fingerings.Add(note);

                    break;
                }

                scanner.SkipWhitespaces();
            }

            if (result.Fingerings.Count != Defaults.Strings)
            {
                this.Report(LogLevel.Error, scanner.LastReadRange,
                            Messages.Error_ChordFingeringNotMatchingStringCount, Defaults.Strings);
                result = null;
                return(false);
            }

            result.Range = anchor.Range;
            return(true);
        }