Skip to content

Commit 0bc8c68

Browse files
committed
added filter support for Guid
1 parent 4c1842e commit 0bc8c68

File tree

10 files changed

+133
-266
lines changed

10 files changed

+133
-266
lines changed

src/GoatQuery/src/Ast/StringLiteral.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
13
public sealed class StringLiteral : QueryExpression
24
{
35
public string Value { get; set; }
@@ -8,6 +10,16 @@ public StringLiteral(Token token, string value) : base(token)
810
}
911
}
1012

13+
public sealed class GuidLiteral : QueryExpression
14+
{
15+
public Guid Value { get; set; }
16+
17+
public GuidLiteral(Token token, Guid value) : base(token)
18+
{
19+
Value = value;
20+
}
21+
}
22+
1123
public sealed class IntegerLiteral : QueryExpression
1224
{
1325
public int Value { get; set; }

src/GoatQuery/src/Evaluator/FilterEvaluator.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public static Result<Expression> Evaluate(QueryExpression expression, ParameterE
2222

2323
switch (exp.Right)
2424
{
25+
case GuidLiteral literal:
26+
value = Expression.Constant(literal.Value, property.Type);
27+
break;
2528
case IntegerLiteral literal:
2629
value = Expression.Constant(literal.Value, property.Type);
2730
break;

src/GoatQuery/src/Lexer/Lexer.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
13
public sealed class QueryLexer
24
{
35
private readonly string _input;
@@ -50,18 +52,24 @@ public Token NextToken()
5052
token.Literal = ReadString();
5153
break;
5254
default:
53-
if (IsLetter(_character))
55+
if (IsLetter(_character) || IsDigit(_character))
5456
{
5557
token.Literal = ReadIdentifier();
58+
if (IsGuid(token.Literal))
59+
{
60+
token.Type = TokenType.GUID;
61+
return token;
62+
}
63+
64+
if (IsDigit(token.Literal[0]))
65+
{
66+
token.Type = TokenType.INT;
67+
return token;
68+
}
69+
5670
token.Type = TokenType.IDENT;
5771
return token;
5872
}
59-
else if (IsDigit(_character))
60-
{
61-
token.Literal = ReadNumber();
62-
token.Type = TokenType.INT;
63-
return token;
64-
}
6573
break;
6674
}
6775

@@ -70,6 +78,11 @@ public Token NextToken()
7078
return token;
7179
}
7280

81+
private bool IsGuid(string value)
82+
{
83+
return Guid.TryParse(value, out _);
84+
}
85+
7386
private string ReadIdentifier()
7487
{
7588
var currentPosition = _position;
@@ -84,7 +97,7 @@ private string ReadIdentifier()
8497

8598
private bool IsLetter(char ch)
8699
{
87-
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_';
100+
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch == '-';
88101
}
89102

90103
private bool IsDigit(char ch)

src/GoatQuery/src/Parser/Parser.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private Result<InfixExpression> ParseFilterStatement()
139139

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

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

154154
switch (_currentToken.Type)
155155
{
156+
case TokenType.GUID:
157+
if (Guid.TryParse(_currentToken.Literal, out var guidValue))
158+
{
159+
statement.Right = new GuidLiteral(_currentToken, guidValue);
160+
}
161+
break;
156162
case TokenType.STRING:
157163
statement.Right = new StringLiteral(_currentToken, _currentToken.Literal);
158164
break;
159165
case TokenType.INT:
160-
if (int.TryParse(_currentToken.Literal, out var value))
166+
if (int.TryParse(_currentToken.Literal, out var intValue))
161167
{
162-
statement.Right = new IntegerLiteral(_currentToken, value);
168+
statement.Right = new IntegerLiteral(_currentToken, intValue);
163169
}
164170
break;
165171
}
@@ -185,11 +191,6 @@ private bool CurrentTokenIs(TokenType token)
185191
return _currentToken.Type == token;
186192
}
187193

188-
private bool PeekTokenIs(TokenType token)
189-
{
190-
return _peekToken.Type == token;
191-
}
192-
193194
private bool PeekTokenIn(params TokenType[] token)
194195
{
195196
return token.Contains(_peekToken.Type);

src/GoatQuery/src/Token/Token.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ public enum TokenType
55
IDENT,
66
STRING,
77
INT,
8+
GUID,
89
LPAREN,
910
RPAREN,
1011
}

src/GoatQuery/tests/Filter/FilterLexerTest.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,17 @@ public static IEnumerable<object[]> Parameters()
169169
new (TokenType.STRING, "10 Test Av"),
170170
}
171171
};
172+
173+
yield return new object[]
174+
{
175+
"id eq e4c7772b-8947-4e46-98ed-644b417d2a08",
176+
new KeyValuePair<TokenType, string>[]
177+
{
178+
new (TokenType.IDENT, "id"),
179+
new (TokenType.IDENT, "eq"),
180+
new (TokenType.GUID, "e4c7772b-8947-4e46-98ed-644b417d2a08"),
181+
}
182+
};
172183
}
173184

174185
[Theory]

src/GoatQuery/tests/Filter/FilterParserTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public sealed class FilterParserTest
88
[InlineData("Age eq 21", "Age", "eq", "21")]
99
[InlineData("Age ne 10", "Age", "ne", "10")]
1010
[InlineData("Name contains 'John'", "Name", "contains", "John")]
11+
[InlineData("Id eq e4c7772b-8947-4e46-98ed-644b417d2a08", "Id", "eq", "e4c7772b-8947-4e46-98ed-644b417d2a08")]
1112
public void Test_ParsingFilterStatement(string input, string expectedLeft, string expectedOperator, string expectedRight)
1213
{
1314
var lexer = new QueryLexer(input);

0 commit comments

Comments
 (0)