Skip to content

Commit

Permalink
excluding more chords
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-zhur committed Oct 5, 2024
1 parent 3e3d3e6 commit 86d38c3
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public static class ChordConstants
(ChordMainType.Dim7, "º", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordMainType.Dim7, "°", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordMainType.Dim7, "o", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordMainType.Dim7, "º7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordMainType.Dim7, "°7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordMainType.Dim7, "o7", MatchCase.ExactOnly, MatchAmbiguity.Safe),

(ChordMainType.Sus2, "sus2", MatchCase.MatchAny, MatchAmbiguity.Safe),
(ChordMainType.Sus2, "s2", MatchCase.ExactOnly, MatchAmbiguity.Safe),
Expand Down Expand Up @@ -67,6 +70,14 @@ public static class ChordConstants
(ChordTypeExtension.XMaj7, "MA7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "M", MatchCase.ExactOnly, MatchAmbiguity.Dangerous),
(ChordTypeExtension.XMaj7, "7M", MatchCase.ExactOnly, MatchAmbiguity.Dangerous),
(ChordTypeExtension.XMaj7, "Δ", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "∆", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "△", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "^", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "Δ7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "∆7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "△7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeExtension.XMaj7, "^7", MatchCase.ExactOnly, MatchAmbiguity.Safe),

(ChordTypeExtension.XMaj9, "maj9", MatchCase.MatchAny, MatchAmbiguity.AlterableDegree),
(ChordTypeExtension.XMaj9, "ma9", MatchCase.ExactOnly, MatchAmbiguity.AlterableDegree),
Expand Down Expand Up @@ -133,11 +144,16 @@ public static class ChordConstants
public static readonly IReadOnlyList<(ChordTypeAmbiguousAddition addition, string representation, MatchCase matchCase, MatchAmbiguity matchAmbiguity)> ChordTypeAmbiguousAdditionRepresentations =
[
(ChordTypeAmbiguousAddition.HalfDiminished7, "ø", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeAmbiguousAddition.HalfDiminished7, "Ø", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeAmbiguousAddition.HalfDiminished7, "ø7", MatchCase.ExactOnly, MatchAmbiguity.Safe),
(ChordTypeAmbiguousAddition.HalfDiminished7, "Ø7", MatchCase.ExactOnly, MatchAmbiguity.Safe),

(ChordTypeAmbiguousAddition.Sharp, "#", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration),
(ChordTypeAmbiguousAddition.Sharp, "♯", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration),
(ChordTypeAmbiguousAddition.Flat, "b", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration),
(ChordTypeAmbiguousAddition.Plus, "+", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration),
(ChordTypeAmbiguousAddition.Minus, "-", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration),
(ChordTypeAmbiguousAddition.Flat, "♭", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration),
(ChordTypeAmbiguousAddition.Plus, "+", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration), // generally means augmented if at the beginning and no degree follows
(ChordTypeAmbiguousAddition.Minus, "-", MatchCase.ExactOnly, MatchAmbiguity.DegreeAlteration), // generally means minor if at the beginning and no degree follows

(ChordTypeAmbiguousAddition.Add9And11, "add9,11", MatchCase.MatchAny, MatchAmbiguity.AlterableDegree),
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

public enum ChordParseError
{
[Obsolete]
NotImplemented,

WhitespaceFragments,
UnexpectedChordTypeToken,
UnreadableRoot,
SameBass,
EmptyString,
BadSymbols,
RomansNotInParentheses,
RomansInParenthesesExpectedOnly,
OnlyIntegerInParentheses,
DuplicateAdditions,
EachExtensionTypeExpectedUnique,
MaxOneMajExtensionExpected,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum ChordTypeExtension
X9,
X11,
X13,

XMaj7,
XMaj9,
XMaj11,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace HarmonyDB.Theory.Chords.Models.Enums;

public enum ChordTypeParseLogic
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ChordTypeParsingOptions
IgnoreTrailingSlashes = true,
IgnoreTrailingStars = true,
QuestionsParsingBehavior = QuestionsParsingBehavior.IgnoreAndTreatOnlyAsPower,
OnlyIntegersInParenthesesAreAddedDegrees = true,
};

public bool TrimWhitespaceFragments { get; set; }
Expand All @@ -22,4 +23,6 @@ public class ChordTypeParsingOptions
public bool IgnoreTrailingStars { get; set; }

public QuestionsParsingBehavior QuestionsParsingBehavior { get; set; } = QuestionsParsingBehavior.Error;

public bool OnlyIntegersInParenthesesAreAddedDegrees { get; set; }
}
103 changes: 88 additions & 15 deletions HarmonyDB.Theory/HarmonyDB.Theory.Chords/Parsers/ChordParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,19 @@ internal static (ChordType? chordType, ChordParseError? error, ChordTypeParseLog
{
var tokens = readonlyTokens.ToList();

#region Removing stars, apostrophes, leading slashes, handling questions. No Star, Apostrophe, Question after this point. Possible middle slashes and separators.
void ReplaceWithASeparator(Func<ChordTypeToken, bool> selector)
=> ReplaceWithASeparator2(x => selector(x.token));

void ReplaceWithASeparator2(Func<(ChordTypeToken token, bool fromParentheses, MatchAmbiguity matchAmbiguity), bool> selector)
{
void ReplaceQuestionWithASeparator()
{
tokens = tokens
.Select(x => x.token.MeaninglessAddition == ChordTypeMeaninglessAddition.Question ? (new(ChordTypeMeaninglessAddition.FragmentSeparator), false, MatchAmbiguity.Safe) : x)
.ToList();
}
tokens = tokens
.Select(x => selector(x) ? (new(ChordTypeMeaninglessAddition.FragmentSeparator), false, MatchAmbiguity.Safe) : x)
.ToList();
}

#region Removing stars, apostrophes, leading slashes, handling questions. No Star, Apostrophe, Question after this point. Possible middle slashes and separators.

{
switch (options.QuestionsParsingBehavior)
{
case QuestionsParsingBehavior.IgnoreAndTreatOnlyAsPower:
Expand All @@ -89,14 +92,14 @@ void ReplaceQuestionWithASeparator()
}
else
{
ReplaceQuestionWithASeparator();
ReplaceWithASeparator(x => x.MeaninglessAddition == ChordTypeMeaninglessAddition.Question);
}

break;
}

case QuestionsParsingBehavior.Ignore:
ReplaceQuestionWithASeparator();
ReplaceWithASeparator(x => x.MeaninglessAddition == ChordTypeMeaninglessAddition.Question);
break;
}

Expand Down Expand Up @@ -134,6 +137,78 @@ void ReplaceQuestionWithASeparator()

#endregion

byte? resultFret = null;
#region Parentheses content, frets. FromParentheses not needed after this point. No romans after this point.

{
if (tokens.Any(x => x.token.Fret.HasValue && !x.fromParentheses))
return (null, ChordParseError.RomansNotInParentheses, null, 1);

var meaningfulFromParentheses = tokens
// separators cannot be from parentheses except when there are multiple things in them.
.Where(x => x.fromParentheses)
.ToList();

if (meaningfulFromParentheses.Any(x => x.token.Fret.HasValue))
{
if (meaningfulFromParentheses.Count > 1)
return (null, ChordParseError.RomansInParenthesesExpectedOnly, null, 2);
else
{
resultFret = meaningfulFromParentheses[0].token.Fret!.Value;
ReplaceWithASeparator2(x => x is { fromParentheses: true, token.Fret: not null });
}
}

if (meaningfulFromParentheses.Any(x => x.matchAmbiguity == MatchAmbiguity.AlterableInt))
{
if (meaningfulFromParentheses.Count == 1)
{
if (!options.OnlyIntegersInParenthesesAreAddedDegrees)
return (null, ChordParseError.OnlyIntegerInParentheses, null, 3);
}
}

if (tokens.Any(x => x.token.Fret.HasValue))
throw new("Could not have happened, all frets filtered out.");
}

#endregion

var allAdditions = ChordTypeAdditions.None;
#region Gathering all additions, checking uniqueness

{
foreach (var addition in tokens.Where(x => x.token.Addition.HasValue).GroupBy(x => x.token.Addition!.Value))
{
if (addition.Count() > 1)
return (null, ChordParseError.DuplicateAdditions, null, 4);

allAdditions |= addition.Key;
}
}

#endregion

#region Extensions tokens unique of each extension type

{
if (tokens.Where(x => x.token.Extension.HasValue).GroupBy(x => x.token.Extension!.Value)
.Any(g => g.Count() > 1))
return (null, ChordParseError.EachExtensionTypeExpectedUnique, null, 5);
}

#endregion

#region Max one maj extension token

{
if (tokens.Count(x => x.token.Extension >= ChordTypeExtension.XMaj7) > 1)
return (null, ChordParseError.MaxOneMajExtensionExpected, null, 6);
}

#endregion

return (null, ChordParseError.NotImplemented, null, 255);
}

Expand Down Expand Up @@ -204,12 +279,10 @@ internal static (List<(string fragment, bool fromParentheses)>? fragments, Chord
}
else
{
inputs =
[
(match.Groups[1].Value, false),
(match.Groups[2].Value, true),
(match.Groups[3].Value, false),
];
inputs = match.Groups[2].Value.Split(',').Select(x => (x, true))
.Prepend((match.Groups[1].Value, false))
.Append((match.Groups[3].Value, false))
.ToList();
}

inputs = inputs.Where(x => x.input != string.Empty).ToList();
Expand Down

0 comments on commit 86d38c3

Please sign in to comment.