in MySQL.Data/src/X/Protocol/X/ExprParser.cs [1128:1204]
Expr IlriExpr()
{
Expr lhs = CompExpr();
List<TokenType> expected = new List<TokenType>(new TokenType[] { TokenType.IS, TokenType.IN, TokenType.LIKE, TokenType.BETWEEN, TokenType.REGEXP, TokenType.NOT, TokenType.OVERLAPS });
while (this.tokenPos < this.tokens.Count && expected.Contains(this.tokens[this.tokenPos].type))
{
bool isNot = false;
if (CurrentTokenTypeEquals(TokenType.NOT))
{
ConsumeToken(TokenType.NOT);
isNot = true;
}
if (this.tokenPos < this.tokens.Count)
{
List<Expr> parameters = new List<Expr>();
parameters.Add(lhs);
string opName = this.tokens[this.tokenPos].value.ToLowerInvariant();
switch (this.tokens[this.tokenPos].type)
{
case TokenType.IS: // for IS, NOT comes AFTER
ConsumeToken(TokenType.IS);
if (CurrentTokenTypeEquals(TokenType.NOT))
{
ConsumeToken(TokenType.NOT);
opName = "is_not";
}
parameters.Add(CompExpr());
break;
case TokenType.IN:
ConsumeToken(TokenType.IN);
if (CurrentTokenTypeEquals(TokenType.LPAREN)) parameters.AddRange(ParenExprList());
else
{
opName = "cont_in";
parameters.Add(CompExpr());
}
break;
case TokenType.LIKE:
ConsumeToken(TokenType.LIKE);
parameters.Add(CompExpr());
if (CurrentTokenTypeEquals(TokenType.ESCAPE))
{
ConsumeToken(TokenType.ESCAPE);
// add as a third (optional) param
parameters.Add(CompExpr());
}
break;
case TokenType.BETWEEN:
ConsumeToken(TokenType.BETWEEN);
parameters.Add(CompExpr());
AssertTokenAt(this.tokenPos, TokenType.AND);
ConsumeToken(TokenType.AND);
parameters.Add(CompExpr());
break;
case TokenType.REGEXP:
ConsumeToken(TokenType.REGEXP);
parameters.Add(CompExpr());
break;
case TokenType.OVERLAPS:
ConsumeToken(TokenType.OVERLAPS);
parameters.Add(CompExpr());
break;
default:
throw new ArgumentException("Unknown token after NOT at pos: " + this.tokenPos);
}
if (isNot)
{
opName = "not_" + opName;
}
Operator builder = new Operator();
builder.Name = opName;
builder.Param.Add(parameters);
lhs = new Expr() { Type = Expr.Types.Type.Operator, Operator = builder };
}
}
return lhs;
}