Esempio n. 1
0
        private static void parseCaster(
            Syntax.Types.Type valueType,
            string _name, out string name,
            out FunctionType.ParameterType[] argList,
            Scope targetScope,
            int _tokenIndex, out int tokenIndex,
            Token[] tokens
            )
        {
            tokenIndex = _tokenIndex;
            name       = $"!as_{ valueType.Name }";

            parseFunction(
                valueType,
                name, out name,
                out argList,
                targetScope,
                tokenIndex, out tokenIndex,
                tokens
                );

            if (argList.Length > 0)
            {
                throw new Exceptions.InvalidCasterDefinitionException(
                          argList.First().DefiningToken,
                          "Casters may not have parameters"
                          );
            }
        }
Esempio n. 2
0
        private static void parseFunction(
            Syntax.Types.Type valueType,
            string _name, out string name,
            out FunctionType.ParameterType[] argList,
            Scope targetScope,
            int _tokenIndex, out int tokenIndex,
            Token[] tokens
            )
        {
            tokenIndex = _tokenIndex;
            name       = _name;

            var token = tokens[tokenIndex];

            if (valueType == null)
            {
                throw new UnexpectedTokenException(token);
            }

            if (name == null && valueType == targetScope.Type)
            {
                name = "!constructor"; // the ! is used as a kind of "escape" because it is impossible for a user created function to contain a ! in its name
            }
            else if (name == null)
            {
                throw new UnexpectedTokenException(token);
            }

            var argListBegin = tokenIndex;

            tokenIndex = ParserHelper.FindClosingScope(tokens, tokenIndex);

            // +1 in Take to include closing bracket, makes things easier in the parse method
            argList = FunctionType.ParseArgumentList(targetScope, tokens.Skip(argListBegin + 1).Take(tokenIndex - argListBegin).ToArray());

            if (name != "!constructor")
            {
                foreach (var param in argList)
                {
                    if (param is FunctionType.InitializerParameterType)
                    {
                        throw new Exceptions.InvalidParameterPropertyInitializerException(
                                  param as FunctionType.InitializerParameterType,
                                  "initializer parameters are only allowed in constructors"
                                  );
                    }
                }
            }
        }
Esempio n. 3
0
        public static void ParseTypes(Scope targetScope, Token[] tokens, TokenTypeValidator _tokenTypeValidator)
        {
            Access    access        = Access.@default;
            TokenType type          = TokenType.unknown;
            string    name          = null;
            Token     definingToken = null;

            Syntax.Types.Type            valueType = null;
            FunctionType.ParameterType[] argList   = null;
            Token[]   genericParamListTokens       = null;
            Token[][] baseTypeListTokens           = null;

            for (int i = 0; i < tokens.Length; ++i)
            {
                var token = tokens[i];
                var tokenTypeValidator = _tokenTypeValidator.WithToken(token);

                switch (token.Value)
                {
                case "public":
                case "protected":
                case "private":
                    if (access != Access.@default)
                    {
                        throw new UnexpectedTokenException(token);
                    }
                    access = accessFromString(token);
                    break;

                case "void":
                    tokenTypeValidator.Validate(TokenType.function);
                    valueType = NullValueNode.Type;
                    break;

                case "namespace":
                case "class":
                case "cast":
                case "interface":
                    type = tokenTypeFromToken(token);
                    tokenTypeValidator.Validate(type);
                    break;

                case "(":
                    if (type == TokenType.unknown)
                    {
                        type = TokenType.function;
                    }
                    if (type == TokenType.function || type == TokenType.cast)
                    {
                        tokenTypeValidator.Validate(type);

                        switch (type)
                        {
                        case TokenType.function: {
                            if (name != null && name.StartsWith("operator_"))
                            {
                                var @operator = name.Substring("operator_".Length);
                                if (!Expression.OperatorOverloadableNames.Contains(@operator))
                                {
                                    throw new InvalidOperatorDefinitionException(
                                              token,
                                              $"Cannot create overload for unknown operator \"{ @operator }\" - function names may not begin with \"operator\" because it is a keyword used for operator overloading"
                                              );
                                }

                                // setting the name like this defines this function as an operator overload, no further action required
                                name          = $"!operator_{ @operator.ToLower() }";
                                definingToken = token;
                            }

                            parseFunction(
                                valueType,
                                name, out name,
                                out argList,
                                targetScope,
                                i, out i,
                                tokens
                                );
                            break;
                        }

                        case TokenType.cast:
                            parseCaster(
                                valueType,
                                name, out name,
                                out argList,
                                targetScope,
                                i, out i,
                                tokens
                                );
                            definingToken = token;
                            break;
                        }
                    }
                    else
                    {
                        throw new UnexpectedTokenException(token);
                    }
                    break;

                case "<":
                    if (type == TokenType.unknown)
                    {
                        type = TokenType.@class;
                    }
                    if (type == TokenType.@class)
                    {
                        tokenTypeValidator.Validate(type);

                        var beginGenericList = i;
                        i = ParserHelper.FindClosingScope(tokens, beginGenericList);
                        genericParamListTokens = tokens.Skip(beginGenericList + 1).Take(i - beginGenericList).ToArray();
                    }
                    break;

                case "{":
                {
                    if (type == TokenType.unknown || name == null)
                    {
                        throw new UnexpectedTokenException(token);
                    }
                    if (access == Access.@default)
                    {
                        access = Access.@public;
                    }

                    var beginScope = i;
                    i = ParserHelper.FindClosingScope(tokens, i);

                    if (genericParamListTokens != null && type != TokenType.@class && type != TokenType.@interface)
                    {
                        throw new UnexpectedTypeParameterException(token);
                    }

                    if (type == TokenType.@namespace)
                    {
                        targetScope.Declare(
                            new Namespace(
                                targetScope,
                                access,
                                name,
                                tokens.Skip(beginScope + 1).Take(i - beginScope - 1).ToArray()
                                )
                            );
                    }
                    else if (type == TokenType.@class)
                    {
                        ClassType classType;
                        if (genericParamListTokens != null)
                        {
                            classType = new GenericClassType(
                                targetScope,
                                access,
                                name,
                                definingToken,
                                tokens.Skip(beginScope + 1).Take(i - beginScope - 1).ToArray(),
                                genericParamListTokens
                                );
                        }
                        else
                        {
                            classType = new ClassType(
                                targetScope,
                                access,
                                name,
                                definingToken,
                                tokens.Skip(beginScope + 1).Take(i - beginScope - 1).ToArray(),
                                baseTypeListTokens
                                );
                        }

                        targetScope.Declare(classType);
                        genericParamListTokens = null;
                    }
                    else if (type == TokenType.function || type == TokenType.cast)
                    {
                        var newFunction = new FunctionType(
                            definingToken,
                            targetScope.Type,
                            access,
                            valueType,
                            name,
                            argList,
                            tokens.Skip(beginScope + 1).Take(i - beginScope - 1).ToArray()
                            );
                        targetScope.Declare(newFunction);
                        argList = null;
                    }
                    else if (type == TokenType.@interface)
                    {
                        if (access != Access.@public && access != Access.@default)
                        {
                            throw new InvalidVisibilityModifierException("interfaces must be have public or default visibility", definingToken);
                        }

                        var newInterface = new InterfaceType(
                            definingToken,
                            targetScope,
                            name,
                            tokens.Skip(beginScope + 1).Take(i - beginScope - 1).ToArray()
                            );
                        targetScope.Declare(newInterface);
                    }

                    access    = Access.@default;
                    type      = TokenType.unknown;
                    name      = null;
                    valueType = null;
                }
                break;

                case ";":
                    if (type == TokenType.unknown)
                    {
                        type = TokenType.variable;
                        tokenTypeValidator.Validate(type);
                        if (name == null || valueType == null)
                        {
                            throw new UnexpectedTokenException(token);
                        }

                        var newMember = new MemberVariableType(
                            tokens[i - 1],
                            targetScope.Type,
                            access,
                            valueType,
                            name
                            );
                        targetScope.Declare(newMember);

                        access    = Access.@default;
                        name      = null;
                        type      = TokenType.unknown;
                        valueType = null;
                    }
                    else if (!_tokenTypeValidator.HasMemberRule(MemberRule.NoPrototypes) && (type == TokenType.function || type == TokenType.cast))
                    {
                        var newFunction = new FunctionType(
                            definingToken,
                            targetScope.Type,
                            access,
                            valueType,
                            name,
                            argList,
                            null
                            );
                        targetScope.Declare(newFunction);
                        argList = null;
                    }
                    else
                    {
                        throw new UnexpectedTokenException(token);
                    }
                    break;

                case ":": {
                    if (type != TokenType.@class)
                    {
                        throw new UnexpectedTokenException(token);
                    }

                    baseTypeListTokens = ClassType.SplitInheritanceListTokens(tokens, i + 1, targetScope, out var inheritanceListEnd);
                    i = inheritanceListEnd - 1;

                    break;
                }

                default: {
                    var temp = "";

                    while (true)
                    {
                        if (SymbolNode.CouldBeIdentifier(token.InArray(), out var m))
                        {
                            temp += m.Value;
                        }
                        else
                        {
                            throw new UnexpectedTokenException(token);
                        }

                        if (i + 2 < tokens.Length && tokens[i + 1].Value == ".")
                        {
                            temp += ".";
                            i    += 2;
                            token = tokens[i];
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (type != TokenType.@class && type != TokenType.@interface && type != TokenType.@namespace && valueType == null)
                    {
                        valueType = targetScope.GetSymbol(temp) ?? throw new UndefinedSymbolException(token, temp, targetScope);
                    }
                    else
                    {
                        if (name != null)
                        {
                            throw new UnexpectedTokenException(token);
                        }
                        name          = temp;
                        definingToken = token;
                    }

                    break;
                }
                }
            }
        }