예제 #1
0
        public ClassDefinition ParseClassDefinition(TokenStream tokens)
        {
            Token           classToken    = tokens.PopExpected("class");
            Token           nameToken     = tokens.PopIdentifier();
            ClassDefinition cd            = new ClassDefinition(this.context, classToken, nameToken);
            List <Token>    inheritTokens = new List <Token>();

            if (tokens.PopIfPresent(":"))
            {
                while (!tokens.IsNext("{"))
                {
                    if (inheritTokens.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }
                    inheritTokens.Add(tokens.PopIdentifier());
                }
            }
            cd.InheritTokens = inheritTokens.ToArray();
            tokens.PopExpected("{");

            Dictionary <string, ICompilationEntity> members = new Dictionary <string, ICompilationEntity>();

            while (!tokens.PopIfPresent("}"))
            {
                string next = tokens.PeekValue();
                if (next == "constructor")
                {
                    if (cd.Constructor != null)
                    {
                        throw new ParserException(tokens.Peek(), "Only one constructor is permitted per class.");
                    }

                    Token constructorToken = tokens.PopExpected("constructor");
                    tokens.PopExpected("(");
                    List <PType> argTypes = new List <PType>();
                    List <Token> argNames = new List <Token>();
                    while (!tokens.PopIfPresent(")"))
                    {
                        if (argTypes.Count > 0)
                        {
                            tokens.PopExpected(",");
                        }
                        argTypes.Add(PType.Parse(tokens));
                        argNames.Add(tokens.PopIdentifier());
                    }
                    cd.Constructor        = new ConstructorDefinition(this.context, constructorToken, argTypes, argNames, cd);
                    this.currentCodeOwner = cd.Constructor;
                    cd.Constructor.Code   = this.ParseCodeBlock(tokens, true).ToArray();
                }
                else
                {
                    ICompilationEntity entity;
                    string             entityName;
                    PType memberType = PType.TryParse(tokens);
                    Token memberName = tokens.PopIdentifier();
                    bool  isMethod   = tokens.IsNext("(");
                    if (isMethod)
                    {
                        tokens.PopExpected("(");
                        List <PType> argTypes = new List <PType>();
                        List <Token> argNames = new List <Token>();
                        while (!tokens.PopIfPresent(")"))
                        {
                            if (argTypes.Count > 0)
                            {
                                tokens.PopExpected(",");
                            }
                            argTypes.Add(PType.Parse(tokens));
                            argNames.Add(tokens.PopIdentifier());
                        }
                        FunctionDefinition fd = new FunctionDefinition(memberName, memberType, argTypes, argNames, this.context, cd);
                        this.currentCodeOwner = fd;
                        List <Executable> code = this.ParseCodeBlock(tokens, true);
                        fd.Code    = code.ToArray();
                        entity     = fd;
                        entityName = fd.Name;
                    }
                    else
                    {
                        FieldDefinition fd = new FieldDefinition(this.context, memberType, memberName, cd);
                        this.currentCodeOwner = fd;
                        Expression initialValue = null;
                        if (tokens.PopIfPresent("="))
                        {
                            initialValue = this.ParseExpression(tokens);
                        }
                        else
                        {
                            if (memberType.IsNullable)
                            {
                                initialValue = new InlineConstant(memberType, memberName, null, cd);
                            }
                            else
                            {
                                switch (memberType.RootValue)
                                {
                                case "double": initialValue = new InlineConstant(memberType, memberName, 0.0, cd); break;

                                case "int": initialValue = new InlineConstant(memberType, memberName, 0, cd); break;

                                case "string": initialValue = new InlineConstant(memberType, memberName, null, cd); break;

                                default: throw new NotImplementedException();
                                }
                            }
                        }
                        tokens.PopExpected(";");
                        fd.Value   = initialValue;
                        entity     = fd;
                        entityName = fd.NameToken.Value;
                    }

                    if (members.ContainsKey(entityName))
                    {
                        throw new ParserException(memberName,
                                                  "There are conflicting members in the class '" + cd.NameToken.Value + "' for the name '" + entityName + "'.");
                    }

                    members[entityName] = entity;
                }
            }

            cd.AddMembers(members);

            return(cd);
        }