📄 dynamicquery.cs
字号:
throw ParseError(Res.DuplicateIdentifier, name);
symbols.Add(name, value);
}
public Expression Parse(Type resultType)
{
int exprPos = token.pos;
Expression expr = ParseExpression();
if (resultType != null)
if ((expr = PromoteExpression(expr, resultType, true)) == null)
throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType));
ValidateToken(TokenId.End, Res.SyntaxError);
return expr;
}
#pragma warning disable 0219
public IEnumerable<DynamicOrdering> ParseOrdering()
{
List<DynamicOrdering> orderings = new List<DynamicOrdering>();
while (true)
{
Expression expr = ParseExpression();
bool ascending = true;
if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending"))
{
NextToken();
}
else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending"))
{
NextToken();
ascending = false;
}
orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending });
if (token.id != TokenId.Comma) break;
NextToken();
}
ValidateToken(TokenId.End, Res.SyntaxError);
return orderings;
}
#pragma warning restore 0219
// ?: operator
Expression ParseExpression()
{
int errorPos = token.pos;
Expression expr = ParseLogicalOr();
if (token.id == TokenId.Question)
{
NextToken();
Expression expr1 = ParseExpression();
ValidateToken(TokenId.Colon, Res.ColonExpected);
NextToken();
Expression expr2 = ParseExpression();
expr = GenerateConditional(expr, expr1, expr2, errorPos);
}
return expr;
}
// ||, or operator
Expression ParseLogicalOr()
{
Expression left = ParseLogicalAnd();
while (token.id == TokenId.DoubleBar || TokenIdentifierIs("or"))
{
Token op = token;
NextToken();
Expression right = ParseLogicalAnd();
CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos);
left = Expression.OrElse(left, right);
}
return left;
}
// &&, and operator
Expression ParseLogicalAnd()
{
Expression left = ParseComparison();
while (token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))
{
Token op = token;
NextToken();
Expression right = ParseComparison();
CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos);
left = Expression.AndAlso(left, right);
}
return left;
}
// =, ==, !=, <>, >, >=, <, <= operators
Expression ParseComparison()
{
Expression left = ParseAdditive();
while (token.id == TokenId.Equal || token.id == TokenId.DoubleEqual ||
token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater ||
token.id == TokenId.GreaterThan || token.id == TokenId.GreaterThanEqual ||
token.id == TokenId.LessThan || token.id == TokenId.LessThanEqual)
{
Token op = token;
NextToken();
Expression right = ParseAdditive();
bool isEquality = op.id == TokenId.Equal || op.id == TokenId.DoubleEqual ||
op.id == TokenId.ExclamationEqual || op.id == TokenId.LessGreater;
if (isEquality && !left.Type.IsValueType && !right.Type.IsValueType)
{
if (left.Type != right.Type)
{
if (left.Type.IsAssignableFrom(right.Type))
{
right = Expression.Convert(right, left.Type);
}
else if (right.Type.IsAssignableFrom(left.Type))
{
left = Expression.Convert(left, right.Type);
}
else
{
throw IncompatibleOperandsError(op.text, left, right, op.pos);
}
}
}
else if (IsEnumType(left.Type) || IsEnumType(right.Type))
{
if (left.Type != right.Type)
{
Expression e;
if ((e = PromoteExpression(right, left.Type, true)) != null)
{
right = e;
}
else if ((e = PromoteExpression(left, right.Type, true)) != null)
{
left = e;
}
else
{
throw IncompatibleOperandsError(op.text, left, right, op.pos);
}
}
}
else
{
CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures),
op.text, ref left, ref right, op.pos);
}
switch (op.id)
{
case TokenId.Equal:
case TokenId.DoubleEqual:
left = GenerateEqual(left, right);
break;
case TokenId.ExclamationEqual:
case TokenId.LessGreater:
left = GenerateNotEqual(left, right);
break;
case TokenId.GreaterThan:
left = GenerateGreaterThan(left, right);
break;
case TokenId.GreaterThanEqual:
left = GenerateGreaterThanEqual(left, right);
break;
case TokenId.LessThan:
left = GenerateLessThan(left, right);
break;
case TokenId.LessThanEqual:
left = GenerateLessThanEqual(left, right);
break;
}
}
return left;
}
// +, -, & operators
Expression ParseAdditive()
{
Expression left = ParseMultiplicative();
while (token.id == TokenId.Plus || token.id == TokenId.Minus ||
token.id == TokenId.Amphersand)
{
Token op = token;
NextToken();
Expression right = ParseMultiplicative();
switch (op.id)
{
case TokenId.Plus:
if (left.Type == typeof(string) || right.Type == typeof(string))
goto case TokenId.Amphersand;
CheckAndPromoteOperands(typeof(IAddSignatures), op.text, ref left, ref right, op.pos);
left = GenerateAdd(left, right);
break;
case TokenId.Minus:
CheckAndPromoteOperands(typeof(ISubtractSignatures), op.text, ref left, ref right, op.pos);
left = GenerateSubtract(left, right);
break;
case TokenId.Amphersand:
left = GenerateStringConcat(left, right);
break;
}
}
return left;
}
// *, /, %, mod operators
Expression ParseMultiplicative()
{
Expression left = ParseUnary();
while (token.id == TokenId.Asterisk || token.id == TokenId.Slash ||
token.id == TokenId.Percent || TokenIdentifierIs("mod"))
{
Token op = token;
NextToken();
Expression right = ParseUnary();
CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.text, ref left, ref right, op.pos);
switch (op.id)
{
case TokenId.Asterisk:
left = Expression.Multiply(left, right);
break;
case TokenId.Slash:
left = Expression.Divide(left, right);
break;
case TokenId.Percent:
case TokenId.Identifier:
left = Expression.Modulo(left, right);
break;
}
}
return left;
}
// -, !, not unary operators
Expression ParseUnary()
{
if (token.id == TokenId.Minus || token.id == TokenId.Exclamation ||
TokenIdentifierIs("not"))
{
Token op = token;
NextToken();
if (op.id == TokenId.Minus && (token.id == TokenId.IntegerLiteral ||
token.id == TokenId.RealLiteral))
{
token.text = "-" + token.text;
token.pos = op.pos;
return ParsePrimary();
}
Expression expr = ParseUnary();
if (op.id == TokenId.Minus)
{
CheckAndPromoteOperand(typeof(INegationSignatures), op.text, ref expr, op.pos);
expr = Expression.Negate(expr);
}
else
{
CheckAndPromoteOperand(typeof(INotSignatures), op.text, ref expr, op.pos);
expr = Expression.Not(expr);
}
return expr;
}
return ParsePrimary();
}
Expression ParsePrimary()
{
Expression expr = ParsePrimaryStart();
while (true)
{
if (token.id == TokenId.Dot)
{
NextToken();
expr = ParseMemberAccess(null, expr);
}
else if (token.id == TokenId.OpenBracket)
{
expr = ParseElementAccess(expr);
}
else
{
break;
}
}
return expr;
}
Expression ParsePrimaryStart()
{
switch (token.id)
{
case TokenId.Identifier:
return ParseIdentifier();
case TokenId.StringLiteral:
return ParseStringLiteral();
case TokenId.IntegerLiteral:
return ParseIntegerLiteral();
case TokenId.RealLiteral:
return ParseRealLiteral();
case TokenId.OpenParen:
return ParseParenExpression();
default:
throw ParseError(Res.ExpressionExpected);
}
}
Expression ParseStringLiteral()
{
ValidateToken(TokenId.StringLiteral);
char quote = token.text[0];
string s = token.text.Substring(1, token.text.Length - 2);
int start = 0;
while (true)
{
int i = s.IndexOf(quote, start);
if (i < 0) break;
s = s.Remove(i, 1);
start = i + 1;
}
if (quote == '\'')
{
if (s.Length != 1)
throw ParseError(Res.InvalidCharacterLiteral);
NextToken();
return CreateLiteral(s[0], s);
}
NextToken();
return CreateLiteral(s, s);
}
Expression ParseIntegerLiteral()
{
ValidateToken(TokenId.IntegerLiteral);
string text = token.text;
if (text[0] != '-')
{
ulong value;
if (!UInt64.TryParse(text, out value))
throw ParseError(Res.InvalidIntegerLiteral, text);
NextToken();
if (value <= (ulong)Int32.MaxValue) return CreateLiteral((int)value, text);
if (value <= (ulong)UInt32.MaxValue) return CreateLiteral((uint)value, text);
if (value <= (ulong)Int64.MaxValue) return CreateLiteral((long)value, text);
return CreateLiteral(value, text);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -