Skip to content

Commit

Permalink
added filter support for Guid
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamess-Lucass committed Jul 23, 2024
1 parent 4c1842e commit 0bc8c68
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 266 deletions.
12 changes: 12 additions & 0 deletions src/GoatQuery/src/Ast/StringLiteral.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;

public sealed class StringLiteral : QueryExpression
{
public string Value { get; set; }
Expand All @@ -8,6 +10,16 @@ public StringLiteral(Token token, string value) : base(token)
}
}

public sealed class GuidLiteral : QueryExpression
{
public Guid Value { get; set; }

public GuidLiteral(Token token, Guid value) : base(token)
{
Value = value;
}
}

public sealed class IntegerLiteral : QueryExpression
{
public int Value { get; set; }
Expand Down
3 changes: 3 additions & 0 deletions src/GoatQuery/src/Evaluator/FilterEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public static Result<Expression> Evaluate(QueryExpression expression, ParameterE

switch (exp.Right)
{
case GuidLiteral literal:
value = Expression.Constant(literal.Value, property.Type);
break;
case IntegerLiteral literal:
value = Expression.Constant(literal.Value, property.Type);
break;
Expand Down
29 changes: 21 additions & 8 deletions src/GoatQuery/src/Lexer/Lexer.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;

public sealed class QueryLexer
{
private readonly string _input;
Expand Down Expand Up @@ -50,18 +52,24 @@ public Token NextToken()
token.Literal = ReadString();
break;
default:
if (IsLetter(_character))
if (IsLetter(_character) || IsDigit(_character))
{
token.Literal = ReadIdentifier();
if (IsGuid(token.Literal))
{
token.Type = TokenType.GUID;
return token;
}

if (IsDigit(token.Literal[0]))
{
token.Type = TokenType.INT;
return token;
}

token.Type = TokenType.IDENT;
return token;
}
else if (IsDigit(_character))
{
token.Literal = ReadNumber();
token.Type = TokenType.INT;
return token;
}
break;
}

Expand All @@ -70,6 +78,11 @@ public Token NextToken()
return token;
}

private bool IsGuid(string value)
{
return Guid.TryParse(value, out _);
}

private string ReadIdentifier()
{
var currentPosition = _position;
Expand All @@ -84,7 +97,7 @@ private string ReadIdentifier()

private bool IsLetter(char ch)
{
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_';
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch == '-';
}

private bool IsDigit(char ch)
Expand Down
17 changes: 9 additions & 8 deletions src/GoatQuery/src/Parser/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private Result<InfixExpression> ParseFilterStatement()

var statement = new InfixExpression(_currentToken, identifier, _currentToken.Literal);

if (!PeekTokenIn(TokenType.STRING, TokenType.INT))
if (!PeekTokenIn(TokenType.STRING, TokenType.INT, TokenType.GUID))
{
return Result.Fail("Invalid value type within filter");
}
Expand All @@ -153,13 +153,19 @@ private Result<InfixExpression> ParseFilterStatement()

switch (_currentToken.Type)
{
case TokenType.GUID:
if (Guid.TryParse(_currentToken.Literal, out var guidValue))
{
statement.Right = new GuidLiteral(_currentToken, guidValue);
}
break;
case TokenType.STRING:
statement.Right = new StringLiteral(_currentToken, _currentToken.Literal);
break;
case TokenType.INT:
if (int.TryParse(_currentToken.Literal, out var value))
if (int.TryParse(_currentToken.Literal, out var intValue))
{
statement.Right = new IntegerLiteral(_currentToken, value);
statement.Right = new IntegerLiteral(_currentToken, intValue);
}
break;
}
Expand All @@ -185,11 +191,6 @@ private bool CurrentTokenIs(TokenType token)
return _currentToken.Type == token;
}

private bool PeekTokenIs(TokenType token)
{
return _peekToken.Type == token;
}

private bool PeekTokenIn(params TokenType[] token)
{
return token.Contains(_peekToken.Type);
Expand Down
1 change: 1 addition & 0 deletions src/GoatQuery/src/Token/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public enum TokenType
IDENT,
STRING,
INT,
GUID,
LPAREN,
RPAREN,
}
Expand Down
11 changes: 11 additions & 0 deletions src/GoatQuery/tests/Filter/FilterLexerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,17 @@ public static IEnumerable<object[]> Parameters()
new (TokenType.STRING, "10 Test Av"),
}
};

yield return new object[]
{
"id eq e4c7772b-8947-4e46-98ed-644b417d2a08",
new KeyValuePair<TokenType, string>[]
{
new (TokenType.IDENT, "id"),
new (TokenType.IDENT, "eq"),
new (TokenType.GUID, "e4c7772b-8947-4e46-98ed-644b417d2a08"),
}
};
}

[Theory]
Expand Down
1 change: 1 addition & 0 deletions src/GoatQuery/tests/Filter/FilterParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public sealed class FilterParserTest
[InlineData("Age eq 21", "Age", "eq", "21")]
[InlineData("Age ne 10", "Age", "ne", "10")]
[InlineData("Name contains 'John'", "Name", "contains", "John")]
[InlineData("Id eq e4c7772b-8947-4e46-98ed-644b417d2a08", "Id", "eq", "e4c7772b-8947-4e46-98ed-644b417d2a08")]
public void Test_ParsingFilterStatement(string input, string expectedLeft, string expectedOperator, string expectedRight)
{
var lexer = new QueryLexer(input);
Expand Down
Loading

0 comments on commit 0bc8c68

Please sign in to comment.