Beispiel #1
0
        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));
            }
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
 // ReSharper disable once UnusedParameter.Local
 private void ValidateToken(TokenId t)
 {
     if (_token.id != t)
     {
         throw ParseException.Create(_token.pos, ErrorMessages.SyntaxError);
     }
 }
Beispiel #6
0
        // = 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);
        }
Beispiel #7
0
 // ReSharper disable once UnusedParameter.Local
 private void ValidateToken(TokenId t, string errorMessage)
 {
     if (_token.id != t)
     {
         throw ParseException.Create(_token.pos, errorMessage);
     }
 }
Beispiel #8
0
 private void ValidateDigit()
 {
     if (!char.IsDigit(_parseChar))
     {
         throw ParseException.Create(_parsePosition, ErrorMessages.DigitExpected);
     }
 }
Beispiel #9
0
        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));
        }
Beispiel #10
0
        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));
        }
Beispiel #11
0
        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]));
        }
Beispiel #12
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));
        }
Beispiel #13
0
        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));
            }
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
        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));
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        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);
            }
        }
Beispiel #18
0
        // 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);
        }
Beispiel #19
0
        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));
        }
Beispiel #20
0
        // 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);
        }
Beispiel #21
0
        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)));
        }
Beispiel #22
0
        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());
        }
Beispiel #23
0
 public void RaiseParseError()
 {
     throw ParseException.Create(str, pos);
 }
Beispiel #24
0
        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;
        }