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); }