Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ Expression ParseLambdaOperator()
Expression ParseOrOperator()
{
Expression left = ParseAndOperator();
while (_textParser.CurrentToken.Id == TokenId.DoubleBar || TokenIdentifierIs("Or") || TokenIdentifierIs("OrElse"))
while (_textParser.CurrentToken.Id == TokenId.DoubleBar)
{
Token op = _textParser.CurrentToken;
_textParser.NextToken();
Expand All @@ -267,7 +267,7 @@ Expression ParseOrOperator()
Expression ParseAndOperator()
{
Expression left = ParseIn();
while (_textParser.CurrentToken.Id == TokenId.DoubleAmphersand || TokenIdentifierIs("And") || TokenIdentifierIs("AndAlso"))
while (_textParser.CurrentToken.Id == TokenId.DoubleAmphersand)
{
Token op = _textParser.CurrentToken;
_textParser.NextToken();
Expand Down
35 changes: 21 additions & 14 deletions src/System.Linq.Dynamic.Core/Tokenizer/TextParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,27 @@ internal class TextParser
private static char[] EscapeCharacters = new[] { '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v' };

// These aliases are supposed to simply the where clause and make it more human readable
// As an addition it is compatible with the OData.Filter specification
private static readonly Dictionary<string, TokenId> _predefinedAliases = new Dictionary<string, TokenId>
private static readonly Dictionary<string, TokenId> _predefinedOperatorAliases = new Dictionary<string, TokenId>(StringComparer.OrdinalIgnoreCase)
{
{"eq", TokenId.Equal},
{"ne", TokenId.ExclamationEqual},
{"neq", TokenId.ExclamationEqual},
{"lt", TokenId.LessThan},
{"le", TokenId.LessThanEqual},
{"gt", TokenId.GreaterThan},
{"ge", TokenId.GreaterThanEqual},
{"and", TokenId.DoubleAmphersand},
{"or", TokenId.DoubleBar},
{"not", TokenId.Exclamation},
{"mod", TokenId.Percent}
{ "eq", TokenId.Equal },
{ "equal", TokenId.Equal },
{ "ne", TokenId.ExclamationEqual },
{ "notequal", TokenId.ExclamationEqual },
{ "neq", TokenId.ExclamationEqual },
{ "lt", TokenId.LessThan },
{ "LessThan", TokenId.LessThan },
{ "le", TokenId.LessThanEqual },
{ "LessThanEqual", TokenId.LessThanEqual },
{ "gt", TokenId.GreaterThan },
{ "GreaterThan", TokenId.GreaterThan },
{ "ge", TokenId.GreaterThanEqual },
{ "GreaterThanEqual", TokenId.GreaterThanEqual },
{ "and", TokenId.DoubleAmphersand },
{ "AndAlso", TokenId.DoubleAmphersand },
{ "or", TokenId.DoubleBar },
{ "OrElse", TokenId.DoubleBar },
{ "not", TokenId.Exclamation },
{ "mod", TokenId.Percent }
};

private readonly string _text;
Expand Down Expand Up @@ -451,7 +458,7 @@ private static Exception ParseError(int pos, string format, params object[] args

private static TokenId GetAliasedTokenId(TokenId tokenId, string alias)
{
return tokenId == TokenId.Identifier && _predefinedAliases.TryGetValue(alias, out TokenId id) ? id : tokenId;
return tokenId == TokenId.Identifier && _predefinedOperatorAliases.TryGetValue(alias, out TokenId id) ? id : tokenId;
}

private static bool IsHexChar(char c)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Linq.Dynamic.Core.Parser;
using System.Linq.Expressions;
using NFluent;
using Xunit;

namespace System.Linq.Dynamic.Core.Tests.Parser
{
public class ExpressionParserTests
{
[Theory]
[InlineData("it == 1", "(x == 1)")]
[InlineData("it eq 1", "(x == 1)")]
[InlineData("it equal 1", "(x == 1)")]
[InlineData("it != 1", "(x != 1)")]
[InlineData("it ne 1", "(x != 1)")]
[InlineData("it neq 1", "(x != 1)")]
[InlineData("it notequal 1", "(x != 1)")]
[InlineData("it lt 1", "(x < 1)")]
[InlineData("it LessThan 1", "(x < 1)")]
[InlineData("it le 1", "(x <= 1)")]
[InlineData("it LessThanEqual 1", "(x <= 1)")]
[InlineData("it gt 1", "(x > 1)")]
[InlineData("it GreaterThan 1", "(x > 1)")]
[InlineData("it ge 1", "(x >= 1)")]
[InlineData("it GreaterThanEqual 1", "(x >= 1)")]
public void Parse_ParseComparisonOperator(string expression, string result)
{
// Arrange
ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
var sut = new ExpressionParser(parameters, expression, null, null);

// Act
var parsedExpression = sut.Parse(null).ToString();

// Assert
Check.That(parsedExpression).Equals(result);
}

[Theory]
[InlineData("it || true", "(x OrElse True)")]
[InlineData("it or true", "(x OrElse True)")]
[InlineData("it OrElse true", "(x OrElse True)")]
public void Parse_ParseOrOperator(string expression, string result)
{
// Arrange
ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
var sut = new ExpressionParser(parameters, expression, null, null);

// Act
var parsedExpression = sut.Parse(null).ToString();

// Assert
Check.That(parsedExpression).Equals(result);
}

[Theory]
[InlineData("it && true", "(x AndAlso True)")]
[InlineData("it and true", "(x AndAlso True)")]
[InlineData("it AndAlso true", "(x AndAlso True)")]
public void Parse_ParseAndOperator(string expression, string result)
{
// Arrange
ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
var sut = new ExpressionParser(parameters, expression, null, null);

// Act
var parsedExpression = sut.Parse(null).ToString();

// Assert
Check.That(parsedExpression).Equals(result);
}
}
}