Refactor message filter grammar and add `~` as an alias for `-` in negated filters for better UX when using CLI

pull/925/head
Oleksii Holub 2 years ago
parent 6c039ebfa6
commit 11414b5937

@ -15,16 +15,17 @@ internal static class FilterGrammar
from close in Character.EqualTo(open)
select value;
private static readonly TextParser<char> FreeCharacter =
Character.Matching(c =>
!char.IsWhiteSpace(c) &&
// Avoid all special tokens used by the grammar
c is not ('(' or ')' or '"' or '\'' or '-' or '|' or '&'),
"any character except whitespace or `(`, `)`, `\"`, `'`, `-`, `|`, `&`"
);
private static readonly TextParser<string> UnquotedString =
Parse.OneOf(EscapedCharacter, FreeCharacter).AtLeastOnce().Text();
Parse.OneOf(
EscapedCharacter,
Character.Matching(
c =>
!char.IsWhiteSpace(c) &&
// Avoid all special tokens used by the grammar
c is not ('(' or ')' or '"' or '\'' or '-' or '~' or '|' or '&'),
"any character except whitespace or `(`, `)`, `\"`, `'`, `-`, `|`, `&`"
)
).AtLeastOnce().Text();
private static readonly TextParser<string> String =
Parse.OneOf(QuotedString, UnquotedString).Named("text string");
@ -64,19 +65,7 @@ internal static class FilterGrammar
.Select(k => (MessageFilter) new HasMessageFilter(k))
.Named("has:<value>");
private static readonly TextParser<MessageFilter> NegatedFilter = Character
.EqualTo('-')
.IgnoreThen(Parse.Ref(() => StandaloneFilter!))
.Select(f => (MessageFilter) new NegatedMessageFilter(f));
private static readonly TextParser<MessageFilter> GroupedFilter =
from open in Character.EqualTo('(')
from content in Parse.Ref(() => BinaryExpressionFilter!).Token()
from close in Character.EqualTo(')')
select content;
private static readonly TextParser<MessageFilter> StandaloneFilter = Parse.OneOf(
GroupedFilter,
private static readonly TextParser<MessageFilter> PrimitiveFilter = Parse.OneOf(
FromFilter,
MentionsFilter,
ReactionFilter,
@ -84,19 +73,33 @@ internal static class FilterGrammar
ContainsFilter
);
private static readonly TextParser<MessageFilter> UnaryExpressionFilter = Parse.OneOf(
NegatedFilter,
StandaloneFilter
);
private static readonly TextParser<MessageFilter> GroupedFilter =
from open in Character.EqualTo('(')
from content in Parse.Ref(() => ChainedFilter!).Token()
from close in Character.EqualTo(')')
select content;
private static readonly TextParser<MessageFilter> BinaryExpressionFilter = Parse.Chain(
private static readonly TextParser<MessageFilter> NegatedFilter = Character
// Dash is annoying to use from CLI due to conflicts with options, so we provide tilde as an alias
.In('-', '~')
.IgnoreThen(Parse.OneOf(GroupedFilter, PrimitiveFilter))
.Select(f => (MessageFilter) new NegatedMessageFilter(f));
private static readonly TextParser<MessageFilter> ChainedFilter = Parse.Chain(
// Operator
Parse.OneOf(
// Explicit operator
Character.In('|', '&').Token().Try(),
// Implicit operator (resolves to 'and')
Character.WhiteSpace.AtLeastOnce().IgnoreThen(Parse.Return(' '))
),
UnaryExpressionFilter,
// Operand
Parse.OneOf(
NegatedFilter,
GroupedFilter,
PrimitiveFilter
),
// Reducer
(op, left, right) => op switch
{
'|' => new BinaryExpressionMessageFilter(left, right, BinaryExpressionKind.Or),
@ -105,5 +108,5 @@ internal static class FilterGrammar
);
public static readonly TextParser<MessageFilter> Filter =
BinaryExpressionFilter.Token().AtEnd();
ChainedFilter.Token().AtEnd();
}
Loading…
Cancel
Save