What's wrong
The chord grammar in Semantics.Music/README.md:91-93 (and #360 §3.1) lets the augmented mark + act as the quality and be followed by an extension number:
body = [ quality ] [ extension ] [ suspension ] { modifier }
quality = minor [ "aug" | "+" ] | "dim" | "°" | "ø" | "aug" | "+" | majorWord
extension = [ majorWord ] number | ...
Under that grammar C+7 is an augmented seventh, and Cm+7 is Cm7#5.
The reader doesn't follow it. ReadAugmentedQuality in Semantics.Music/ChordSymbolReader.cs:112 takes + as the quality only when the next character is not a digit:
if (TryTake("aug") || (Peek('+') && !IsDigit(PeekNext()) && TryTake("+")))
When a digit follows, the + is left for the modifier loop. There TryReadAlteration reads it as a sharp, and it accepts only 5, 9 or 11 after a sharp. So:
+7 and +13 are not valid alterations, and the whole symbol is rejected.
+9 and +11 are read as #9 or #11 added to a plain major triad with no seventh.
Before #362, C+7, C+9, C+11 and C+13 all parsed as augmented chords. Neither ChordGrammarTests nor ChordRoundTripTests covers a leading + followed by a number; the corpus has only C+, C7+ and C7+5.
Reproduction
Chord.TryParse / ToString() / ChordTones() against the built library at 022c8a4, compared with a build at 268a90e, the commit before #362:
| Input |
Main today |
Before #362 |
Intended |
C+7 |
rejected |
Caug7 [0,4,8,10] |
Caug7 |
C+13 |
rejected |
aug13 |
Caug13 |
Cm+7 |
rejected |
Caug7 (wrong third, #340) |
Cm7#5 [0,3,8,10] |
C+9 |
C(#9) [0,4,7,15] |
Caug9 [0,4,8,10,14] |
Caug9 [0,4,8,10,14] |
C+11 |
C(#11) [0,4,7,18] |
aug11 |
Caug11 |
These spellings work today:
C+ → Caug
C+maj7 → Caugmaj7
C9+ → Caug9
C7+ → Caug7
C-7 → Cm7
C-13 → Cm13
So a body-start - followed by a number is read as a quality, but a body-start + followed by a number is not.
Why it matters
Suggested fix / acceptance criteria
- At the start of the body, after the optional minor mark, read
+ as the augmented mark whether or not a digit follows, the same way a body-start - is already handled. Keep + as a sharp only in modifier position, after the extension.
- These must parse as follows:
C+7 → Caug7 [0,4,8,10]
C+9 → Caug9 [0,4,8,10,14]
C+11 and C+13 → augmented 11th and 13th chords
Cm+7 → Cm7#5 [0,3,8,10]
- These must not change:
C+, C+5 → Caug, C7+, C7+5, C7+9 → C7#9, C9+ → Caug9, Cadd9(#11).
- Add the rows above to
Parse_GrammarSpellings_KeepTheirMeaning. The existing exhaustive round-trip test should still pass.
Related: #345 covers + after a digit (C7+9), and #340 covers the third in Cm+. Neither covers a leading + before a number.
What's wrong
The chord grammar in
Semantics.Music/README.md:91-93(and #360 §3.1) lets the augmented mark+act as the quality and be followed by an extension number:Under that grammar
C+7is an augmented seventh, andCm+7is Cm7#5.The reader doesn't follow it.
ReadAugmentedQualityinSemantics.Music/ChordSymbolReader.cs:112takes+as the quality only when the next character is not a digit:When a digit follows, the
+is left for the modifier loop. ThereTryReadAlterationreads it as a sharp, and it accepts only5,9or11after a sharp. So:+7and+13are not valid alterations, and the whole symbol is rejected.+9and+11are read as#9or#11added to a plain major triad with no seventh.Before #362,
C+7,C+9,C+11andC+13all parsed as augmented chords. NeitherChordGrammarTestsnorChordRoundTripTestscovers a leading+followed by a number; the corpus has onlyC+,C7+andC7+5.Reproduction
Chord.TryParse/ToString()/ChordTones()against the built library at022c8a4, compared with a build at268a90e, the commit before #362:C+7Caug7[0,4,8,10]Caug7C+13Caug13Cm+7Caug7(wrong third, #340)Cm7#5[0,3,8,10]C+9C(#9)[0,4,7,15]Caug9[0,4,8,10,14]Caug9[0,4,8,10,14]C+11C(#11)[0,4,7,18]Caug11These spellings work today:
C+→CaugC+maj7→Caugmaj7C9+→Caug9C7+→Caug7C-7→Cm7C-13→Cm13So a body-start
-followed by a number is read as a quality, but a body-start+followed by a number is not.Why it matters
C+7andC+9are the standard lead-sheet spellings of the augmented seventh and augmented ninth.Progression.Parse,Section.ParseandArrangement.Parse. Redesign chord symbols: one grammar for Chord.Parse and Chord.ToString (fixes #300 #322 #336 #340 #341 #344 #345 #346 #358) #360 kept a legacy reader specifically so that previously parseable text would keep parsing.C+9andC+11are worse than a rejection. They silently produce a different chord: no seventh, a perfect fifth instead of an augmented one, and Bump MSTest.TestFramework from 3.10.2 to 4.0.2 #9 in place of 9.Suggested fix / acceptance criteria
+as the augmented mark whether or not a digit follows, the same way a body-start-is already handled. Keep+as a sharp only in modifier position, after the extension.C+7→Caug7[0,4,8,10]C+9→Caug9[0,4,8,10,14]C+11andC+13→ augmented 11th and 13th chordsCm+7→Cm7#5[0,3,8,10]C+,C+5→Caug,C7+,C7+5,C7+9→C7#9,C9+→Caug9,Cadd9(#11).Parse_GrammarSpellings_KeepTheirMeaning. The existing exhaustive round-trip test should still pass.Related: #345 covers
+after a digit (C7+9), and #340 covers the third inCm+. Neither covers a leading+before a number.