public static Expression GenerateConversion(Expression expr, Type type, int errorPos) { var exprType = expr.Type; if (exprType == type) { return(expr); } //if (exprType.IsValueType && type.IsValueType) //{ // if ((IsNullableType(exprType) || IsNullableType(type)) && // GetNonNullableType(exprType) == GetNonNullableType(type)) // return Expression.Convert(expr, type); // if ((IsNumericType(exprType) || IsEnumType(exprType)) && // (IsNumericType(type)) || IsEnumType(type)) // return Expression.ConvertChecked(expr, type); //} //if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) || // exprType.IsInterface || type.IsInterface) //{ // return Expression.Convert(expr, type); //} try { return(Expression.ConvertChecked(expr, type)); } catch (InvalidOperationException) { throw ParseException.Create(errorPos, ErrorMessages.CannotConvertValue, Types.GetTypeName(exprType), Types.GetTypeName(type)); } }
private Expression ParsePrimaryStart() { switch (_token.id) { case TokenId.Identifier: return(ParseIdentifier()); case TokenId.CharLiteral: return(ParseCharLiteral()); case TokenId.StringLiteral: return(ParseStringLiteral()); case TokenId.IntegerLiteral: return(ParseIntegerLiteral()); case TokenId.RealLiteral: return(ParseRealLiteral()); case TokenId.OpenParen: return(ParseParenExpression()); case TokenId.End: return(Expression.Empty()); default: throw ParseException.Create(_token.pos, ErrorMessages.ExpressionExpected); } }
private Expression ParseTypeKeyword(Type type) { var errorPos = _token.pos; NextToken(); if (_token.id == TokenId.Question) { if (!type.IsValueType || Types.IsNullableType(type)) { throw ParseException.Create(errorPos, ErrorMessages.TypeHasNoNullableForm, Types.GetTypeName(type)); } type = typeof(Nullable <>).MakeGenericType(type); NextToken(); } //if (token.id == TokenId.OpenParen) //{ // return ParseTypeConstructor(type, errorPos); //} if (_token.id == TokenId.CloseParen) { return(Expression.Constant(type)); } ValidateToken(TokenId.Dot, ErrorMessages.DotOrOpenParenExpected); NextToken(); return(ParseMemberAccess(type, null)); }
private Expression ParseExtensionMethodInvocation(Type type, Expression instance, int errorPos, string id, Expression[] args) { var extensionMethodsArguments = new Expression[args.Length + 1]; extensionMethodsArguments[0] = instance; args.CopyTo(extensionMethodsArguments, 1); var matchMethods = _arguments.GetExtensionMethods(id); var extensionMethods = Expressions.FindBestMethod(matchMethods, extensionMethodsArguments); if (extensionMethods.Length > 1) { throw ParseException.Create(errorPos, ErrorMessages.AmbiguousMethodInvocation, id, Types.GetTypeName(type)); } if (extensionMethods.Length == 1) { var method = extensionMethods[0]; extensionMethodsArguments = method.PromotedParameters; return(Expression.Call((MethodInfo)method.MethodBase, extensionMethodsArguments)); } return(null); }
// ReSharper disable once UnusedParameter.Local private void ValidateToken(TokenId t) { if (_token.id != t) { throw ParseException.Create(_token.pos, ErrorMessages.SyntaxError); } }
// = operator private Expression ParseAssignment() { var left = ParseConditional(); if (_token.id == TokenId.Equal) { if (!_arguments.Settings.AssignmentOperators.HasFlag(AssignmentOperators.AssignmentEqual)) { throw new AssignmentOperatorDisabledException("=", _token.pos); } if (!Expressions.IsWritable(left)) { throw ParseException.Create(_token.pos, ErrorMessages.ExpressionMustBeWritable); } NextToken(); var right = ParseAssignment(); var promoted = Expressions.PromoteExpression(right, left.Type, true); if (promoted == null) { throw ParseException.Create(_token.pos, ErrorMessages.CannotConvertValue, Types.GetTypeName(right.Type), Types.GetTypeName(left.Type)); } left = Expression.Assign(left, promoted); } return(left); }
// ReSharper disable once UnusedParameter.Local private void ValidateToken(TokenId t, string errorMessage) { if (_token.id != t) { throw ParseException.Create(_token.pos, errorMessage); } }
private void ValidateDigit() { if (!char.IsDigit(_parseChar)) { throw ParseException.Create(_parsePosition, ErrorMessages.DigitExpected); } }
public static Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos) { if (test.Type != typeof(bool)) { throw ParseException.Create(errorPos, ErrorMessages.FirstExprMustBeBool); } if (expr1.Type != expr2.Type) { var expr1As2 = expr2 != ParserConstants.NullLiteralExpression ? PromoteExpression(expr1, expr2.Type, true) : null; var expr2As1 = expr1 != ParserConstants.NullLiteralExpression ? PromoteExpression(expr2, expr1.Type, true) : null; if (expr1As2 != null && expr2As1 == null) { expr1 = expr1As2; } else if (expr2As1 != null && expr1As2 == null) { expr2 = expr2As1; } else { var type1 = expr1 != ParserConstants.NullLiteralExpression ? expr1.Type.Name : "null"; var type2 = expr2 != ParserConstants.NullLiteralExpression ? expr2.Type.Name : "null"; if (expr1As2 != null) { throw ParseException.Create(errorPos, ErrorMessages.BothTypesConvertToOther, type1, type2); } throw ParseException.Create(errorPos, ErrorMessages.NeitherTypeConvertsToOther, type1, type2); } } return(Expression.Condition(test, expr1, expr2)); }
private Expression ParseDelegateInvocation(Expression delegateExp, int errorPos) { var args = ParseArgumentList(); if (!_expressions.PrepareDelegateInvoke(delegateExp.Type, ref args)) { throw ParseException.Create(errorPos, ErrorMessages.ArgsIncompatibleWithDelegate); } return(Expression.Invoke(delegateExp, args)); }
private Expression ParseCharLiteral() { ValidateToken(TokenId.CharLiteral); var s = _token.text.Substring(1, _token.text.Length - 2); s = EvalEscapeStringLiteral(s); if (s.Length != 1) { throw ParseException.Create(_token.pos, ErrorMessages.InvalidCharacterLiteral); } NextToken(); return(Expressions.CreateLiteral(s[0])); }
private Expression ParseElementAccess(Expression expr) { var errorPos = _token.pos; ValidateToken(TokenId.OpenBracket, ErrorMessages.OpenParenExpected); NextToken(); var args = ParseArguments(); ValidateToken(TokenId.CloseBracket, ErrorMessages.CloseBracketOrCommaExpected); NextToken(); if (expr.Type.IsArray) { if (expr.Type.GetArrayRank() != args.Length) { throw ParseException.Create(errorPos, ErrorMessages.IncorrectNumberOfIndexes); } for (int i = 0; i < args.Length; i++) { args[i] = Expressions.PromoteExpression(args[i], typeof(int), true); if (args[i] == null) { throw ParseException.Create(errorPos, ErrorMessages.InvalidIndex); } } return(Expression.ArrayAccess(expr, args)); } var applicableMethods = Expressions.FindIndexer(expr.Type, args); if (applicableMethods.Length == 0) { throw ParseException.Create(errorPos, ErrorMessages.NoApplicableIndexer, Types.GetTypeName(expr.Type)); } if (applicableMethods.Length > 1) { throw ParseException.Create(errorPos, ErrorMessages.AmbiguousIndexerInvocation, Types.GetTypeName(expr.Type)); } var indexer = (Expressions.IndexerData)applicableMethods[0]; return(Expression.Property(expr, indexer.Indexer, indexer.PromotedParameters)); }
private Expression ParseIntegerLiteral() { ValidateToken(TokenId.IntegerLiteral); var text = _token.text; if (text[0] != '-') { if (!ulong.TryParse(text, ParseLiteralUnsignedNumberStyle, ParseCulture, out ulong value)) { throw ParseException.Create(_token.pos, ErrorMessages.InvalidIntegerLiteral, text); } NextToken(); if (value <= int.MaxValue) { return(Expressions.CreateLiteral((int)value)); } if (value <= uint.MaxValue) { return(Expressions.CreateLiteral((uint)value)); } if (value <= long.MaxValue) { return(Expressions.CreateLiteral((long)value)); } return(Expressions.CreateLiteral(value)); } else { if (!long.TryParse(text, ParseLiteralNumberStyle, ParseCulture, out long value)) { throw ParseException.Create(_token.pos, ErrorMessages.InvalidIntegerLiteral, text); } NextToken(); if (value >= int.MinValue && value <= int.MaxValue) { return(Expressions.CreateLiteral((int)value)); } return(Expressions.CreateLiteral(value)); } }
private Expression ParsePrimary() { var tokenPos = _token.pos; var expr = ParsePrimaryStart(); while (true) { if (_token.id == TokenId.Dot) { NextToken(); expr = ParseMemberAccess(null, expr); } else if (_token.id == TokenId.QuestionDot) { NextToken(); expr = Expressions.GenerateConditional(Expressions.GenerateEqual(expr, ParserConstants.NullLiteralExpression), ParserConstants.NullLiteralExpression, ParseMemberAccess(null, expr), _token.pos); } else if (_token.id == TokenId.OpenBracket) { expr = ParseElementAccess(expr); } else if (_token.id == TokenId.OpenParen) { var lambda = expr as LambdaExpression; if (lambda != null) { return(ParseLambdaInvocation(lambda, tokenPos)); } if (typeof(Delegate).IsAssignableFrom(expr.Type)) { expr = ParseDelegateInvocation(expr, tokenPos); } else { throw ParseException.Create(tokenPos, ErrorMessages.InvalidMethodCall, Types.GetTypeName(expr.Type)); } } else { break; } } return(expr); }
public Expression GeneratePropertyOrFieldExpression(Type type, Expression instance, int errorPos, string propertyOrFieldName) { var member = FindPropertyOrField(type, propertyOrFieldName, instance == null); if (member != null) { return(member is PropertyInfo? Expression.Property(instance, (PropertyInfo)member) : Expression.Field(instance, (FieldInfo)member)); } if (Types.IsDynamicType(type) || Expressions.IsDynamicExpression(instance)) { return(Expressions.GenerateDynamicProperty(type, instance, propertyOrFieldName)); } throw ParseException.Create(errorPos, ErrorMessages.UnknownPropertyOrField, propertyOrFieldName, Types.GetTypeName(type)); }
private Expression ParseNormalMethodInvocation(Type type, Expression instance, int errorPos, string id, Expression[] args) { var applicableMethods = _expressions.FindMethods(type, id, instance == null, args); if (applicableMethods.Length > 1) { throw ParseException.Create(errorPos, ErrorMessages.AmbiguousMethodInvocation, id, Types.GetTypeName(type)); } if (applicableMethods.Length == 1) { var method = applicableMethods[0]; return(Expression.Call(instance, (MethodInfo)method.MethodBase, method.PromotedParameters)); } return(null); }
private char EvalEscapeChar(char source) { switch (source) { case '\'': return('\''); case '"': return('"'); case '\\': return('\\'); case '0': return('\0'); case 'a': return('\a'); case 'b': return('\b'); case 'f': return('\f'); case 'n': return('\n'); case 'r': return('\r'); case 't': return('\t'); case 'v': return('\v'); default: throw ParseException.Create(_token.pos, ErrorMessages.InvalidEscapeSequence); } }
// Working context implementation //Expression ParseIt() //{ // if (it == null) // throw ParseError(ErrorMessages.NoItInScope); // NextToken(); // return it; //} //Expression ParseIif() //{ // int errorPos = token.pos; // NextToken(); // Expression[] args = ParseArgumentList(); // if (args.Length != 3) // throw ParseError(errorPos, ErrorMessages.IifRequiresThreeArgs); // return GenerateConditional(args[0], args[1], args[2], errorPos); //} private Expression ParseTypeof() { var errorPos = _token.pos; NextToken(); var args = ParseArgumentList(); if (args.Length != 1) { throw ParseException.Create(errorPos, ErrorMessages.TypeofRequiresOneArg); } var constExp = args[0] as ConstantExpression; if (constExp == null || !(constExp.Value is Type)) { throw ParseException.Create(errorPos, ErrorMessages.TypeofRequiresAType); } return(constExp); }
private Expression ParseRealLiteral() { ValidateToken(TokenId.RealLiteral); var text = _token.text; object value = null; var last = text[text.Length - 1]; if (last == 'F' || last == 'f') { if (float.TryParse(text.Substring(0, text.Length - 1), ParseLiteralDecimalNumberStyle, ParseCulture, out float f)) { value = f; } } else if (last == 'M' || last == 'm') { if (decimal.TryParse(text.Substring(0, text.Length - 1), ParseLiteralDecimalNumberStyle, ParseCulture, out decimal dc)) { value = dc; } } else { if (double.TryParse(text, ParseLiteralDecimalNumberStyle, ParseCulture, out double d)) { value = d; } } if (value == null) { throw ParseException.Create(_token.pos, ErrorMessages.InvalidRealLiteral, text); } NextToken(); return(Expressions.CreateLiteral(value)); }
// is, as operators private Expression ParseTypeTesting() { var left = ParseAdditive(); while (_token.text == ParserConstants.KeywordIs || _token.text == ParserConstants.KeywordAs) { var typeOperator = _token.text; var op = _token; NextToken(); Type knownType; if (!_arguments.TryGetKnownType(_token.text, out knownType)) { throw ParseException.Create(op.pos, ErrorMessages.TypeIdentifierExpected); } if (typeOperator == ParserConstants.KeywordIs) { left = Expression.TypeIs(left, knownType); } else if (typeOperator == ParserConstants.KeywordAs) { left = Expression.TypeAs(left, knownType); } else { throw ParseException.Create(_token.pos, ErrorMessages.SyntaxError); } NextToken(); } return(left); }
private Expression ParseNew() { NextToken(); ValidateToken(TokenId.Identifier, ErrorMessages.IdentifierExpected); Type newType; if (!_arguments.TryGetKnownType(_token.text, out newType)) { throw new UnknownIdentifierException(_token.text, _token.pos); } NextToken(); var args = ParseArgumentList(); var constructor = newType.GetConstructor(args.Select(p => p.Type).ToArray()); if (constructor == null) { throw ParseException.Create(_token.pos, ErrorMessages.NoApplicableConstructor, newType); } return(Expression.MemberInit(Expression.New(constructor, args))); }
private string EvalEscapeStringLiteral(string source) { var builder = new StringBuilder(); for (int i = 0; i < source.Length; i++) { var c = source[i]; if (c == '\\') { if ((i + 1) == source.Length) { throw ParseException.Create(_token.pos, ErrorMessages.InvalidEscapeSequence); } builder.Append(EvalEscapeChar(source[++i])); } else { builder.Append(c); } } return(builder.ToString()); }
public void RaiseParseError() { throw ParseException.Create(str, pos); }
private void NextToken() { while (char.IsWhiteSpace(_parseChar)) { NextChar(); } TokenId t; var tokenPos = _parsePosition; switch (_parseChar) { case '!': NextChar(); if (_parseChar == '=') { NextChar(); t = TokenId.ExclamationEqual; } else { t = TokenId.Exclamation; } break; case '%': NextChar(); t = TokenId.Percent; break; case '&': NextChar(); if (_parseChar == '&') { NextChar(); t = TokenId.DoubleAmphersand; } else { t = TokenId.Amphersand; } break; case '(': NextChar(); t = TokenId.OpenParen; break; case ')': NextChar(); t = TokenId.CloseParen; break; case '*': NextChar(); t = TokenId.Asterisk; break; case '+': NextChar(); t = TokenId.Plus; break; case ',': NextChar(); t = TokenId.Comma; break; case '-': NextChar(); t = TokenId.Minus; break; case '.': NextChar(); if (char.IsDigit(_parseChar)) { t = TokenId.RealLiteral; do { NextChar(); } while (char.IsDigit(_parseChar)); if (_parseChar == 'E' || _parseChar == 'e') { t = TokenId.RealLiteral; NextChar(); if (_parseChar == '+' || _parseChar == '-') { NextChar(); } ValidateDigit(); do { NextChar(); } while (char.IsDigit(_parseChar)); } if (_parseChar == 'F' || _parseChar == 'f' || _parseChar == 'M' || _parseChar == 'm') { NextChar(); } break; } t = TokenId.Dot; break; case '/': NextChar(); t = TokenId.Slash; break; case ':': NextChar(); t = TokenId.Colon; break; case '<': NextChar(); if (_parseChar == '=') { NextChar(); t = TokenId.LessThanEqual; } else { t = TokenId.LessThan; } break; case '=': NextChar(); if (_parseChar == '=') { NextChar(); t = TokenId.DoubleEqual; } else { t = TokenId.Equal; } break; case '>': NextChar(); if (_parseChar == '=') { NextChar(); t = TokenId.GreaterThanEqual; } else { t = TokenId.GreaterThan; } break; case '?': NextChar(); if (_parseChar == '.') { NextChar(); t = TokenId.QuestionDot; } else if (_parseChar == '?') { NextChar(); t = TokenId.QuestionQuestion; } else { t = TokenId.Question; } break; case '[': NextChar(); t = TokenId.OpenBracket; break; case ']': NextChar(); t = TokenId.CloseBracket; break; case '|': NextChar(); if (_parseChar == '|') { NextChar(); t = TokenId.DoubleBar; } else { t = TokenId.Bar; } break; case '"': NextChar(); bool isEscapeS = false; bool isEndS = _parseChar == '\"'; while (_parsePosition < _expressionTextLength && !isEndS) { isEscapeS = _parseChar == '\\' && !isEscapeS; NextChar(); isEndS = (_parseChar == '\"' && !isEscapeS); } if (_parsePosition == _expressionTextLength) { throw ParseException.Create(_parsePosition, ErrorMessages.UnterminatedStringLiteral); } NextChar(); t = TokenId.StringLiteral; break; case '\'': NextChar(); bool isEscapeC = false; bool isEndC = false; while (_parsePosition < _expressionTextLength && !isEndC) { isEscapeC = _parseChar == '\\' && !isEscapeC; NextChar(); isEndC = (_parseChar == '\'' && !isEscapeC); } if (_parsePosition == _expressionTextLength) { throw ParseException.Create(_parsePosition, ErrorMessages.UnterminatedStringLiteral); } NextChar(); t = TokenId.CharLiteral; break; case '^': NextChar(); t = TokenId.Caret; break; default: if (char.IsLetter(_parseChar) || _parseChar == '@' || _parseChar == '_') { do { NextChar(); } while (char.IsLetterOrDigit(_parseChar) || _parseChar == '_'); t = TokenId.Identifier; break; } if (char.IsDigit(_parseChar)) { t = TokenId.IntegerLiteral; do { NextChar(); } while (char.IsDigit(_parseChar)); if (_parseChar == '.') { NextChar(); if (char.IsDigit(_parseChar)) { t = TokenId.RealLiteral; do { NextChar(); } while (char.IsDigit(_parseChar)); } else { PreviousChar(); break; } } if (_parseChar == 'E' || _parseChar == 'e') { t = TokenId.RealLiteral; NextChar(); if (_parseChar == '+' || _parseChar == '-') { NextChar(); } ValidateDigit(); do { NextChar(); } while (char.IsDigit(_parseChar)); } if (_parseChar == 'F' || _parseChar == 'f' || _parseChar == 'M' || _parseChar == 'm') { t = TokenId.RealLiteral; NextChar(); } break; } if (_parsePosition == _expressionTextLength) { t = TokenId.End; break; } throw ParseException.Create(_parsePosition, ErrorMessages.InvalidCharacter, _parseChar); } _token.id = t; _token.text = _expressionText.Substring(tokenPos, _parsePosition - tokenPos); _token.pos = tokenPos; }