private void ParseAndAddMemberToStruct(Token variableType, Token structName, ScriptStruct structDefinition, Token parentStruct) { _source.IgnoreAsteriskIfPresent(); Token memberName = _source.ReadNextToken(); if ((memberName is KeywordToken) || (memberName is OperatorToken) || (memberName is ModifierToken)) { throw new CompilerMessage(ErrorCode.TokenAlreadyDefined, "Cannot use '" + memberName.Name + "' as variable name since it has another meaning"); } string mangledName; memberName = GetTokenForStructMember(structName, memberName, out mangledName); if (memberName != null) { throw new CompilerMessage(ErrorCode.TokenAlreadyDefined, "Member '" + mangledName + "' already exists"); } memberName = new Token(mangledName, true); // TODO: Set necessary fields on new token for this struct member _tokenizedScript.AddToken(memberName); CompilerUtils.SetArrayPropertiesOnTokenFromStream(_source, memberName); if (_source.NextIsKeyword(PredefinedSymbol.OpenParenthesis)) { VerifyModifiersAgainstType(ModifierTargets.MemberFunction); VerifyReturnTypeValidForFunction(variableType); ScriptFunction func = new ScriptFunction(variableType, memberName); ParseFunctionParameterList(func); func.IsPrototypeOnly = true; } else { VerifyModifiersAgainstType(ModifierTargets.MemberVariable); ProcessVariableDeclaration(variableType, structDefinition, parentStruct, _state.NextTokenModifiers); } }
private FixedOffsetVariable ProcessVariableDeclaration(Token variableType, DataGroup container, Token parent, Modifiers modifiers) { FixedOffsetVariable newVariable; int thisSize = 0; if (variableType.Type == TokenType.StructType) { ScriptStruct childStruct = (ScriptStruct)variableType.Value; if (childStruct.IsManaged) { thisSize = FixedOffsetVariable.POINTER_SIZE_IN_BYTES; newVariable = new FixedOffsetVariable(variableType, container.SizeInBytes, true); if ((childStruct != container) && (parent != null) && (childStruct.HasNonImportedMemberOfType(parent))) { throw new CompilerMessage(ErrorCode.CircularReference, "The type '" + childStruct.Name + "' has a reference to this struct, so you cannot also have a reference this way round"); } } else if (childStruct == container) { throw new CompilerMessage(ErrorCode.StructInsideItself, "A struct cannot be contained within itself"); } else { thisSize = childStruct.SizeInBytes; newVariable = new FixedOffsetVariable(variableType, container.SizeInBytes, thisSize); } } else if (variableType is ScalarVariableTypeToken) { thisSize = ((ScalarVariableTypeToken)variableType).SizeInBytes; newVariable = new FixedOffsetVariable(variableType, container.SizeInBytes, thisSize); } else if (variableType.Type == TokenType.EnumType) { thisSize = FixedOffsetVariable.ENUM_SIZE_IN_BYTES; newVariable = new FixedOffsetVariable(variableType, container.SizeInBytes, thisSize); } else { throw new CompilerMessage(ErrorCode.CannotUseTypeInStruct, "Cannot add variable of type '" + variableType.Name + "' to struct"); } newVariable.IsAttributeProperty = modifiers.HasModifier(Modifiers.ATTRIBUTE); newVariable.IsImported = modifiers.HasModifier(Modifiers.IMPORT); if ((newVariable.IsAttributeProperty) && (!newVariable.IsImported)) { throw new CompilerMessage(ErrorCode.AttributesMustBeImported, "Attribute types must be imported"); } if ((newVariable.IsImported) && (!newVariable.IsAttributeProperty) && (parent != null)) { throw new CompilerMessage(ErrorCode.InvalidUseOfKeyword, "'import' is invalid in this context"); } if (newVariable.IsImported) { // No memory needed for imported vars newVariable.Offset = 0; thisSize = 0; } container.Members.Add(newVariable); container.SizeInBytes += thisSize; return(newVariable); }
private ScriptStruct ProcessStructDeclaration() { VerifyModifiersAgainstType(ModifierTargets.Struct); Modifiers prototypeModifiers = null; Token structName = _source.ReadNextToken(); if (structName.Defined) { if ((structName.Type == TokenType.StructType) && (structName.StructType.PrototypeOnly)) { prototypeModifiers = structName.StructType.Modifiers; } else { throw new CompilerMessage(ErrorCode.TokenAlreadyDefined, "Token '" + structName.Name + "' is already defined"); } } ScriptStruct structDefinition = new ScriptStruct(structName.Name); structDefinition.Modifiers = _state.NextTokenModifiers; structName.Define(TokenType.StructType, structDefinition); structName.IsVariableType = true; if (_state.IsModifierPresent(PredefinedSymbol.Managed)) { structDefinition.IsManaged = true; } _state.NextTokenModifiers = new Modifiers(); if (_source.NextIsKeyword(PredefinedSymbol.Semicolon)) { structDefinition.PrototypeOnly = true; return(structDefinition); } if (prototypeModifiers != null) { if (!structDefinition.Modifiers.HasSameModifiers(prototypeModifiers)) { RecordError(ErrorCode.DifferentModifierInPrototype, "This struct has different modifiers to the prototype"); } } if (_source.NextIsKeyword(PredefinedSymbol.Extends)) { Token structToExtend = _source.ReadNextAsVariableType(); if (structToExtend.Type != TokenType.StructType) { RecordError(ErrorCode.StructNameExpected, "Struct name expected at '" + structToExtend.Name + "'"); } else { ScriptStruct baseStructDefinition = ((ScriptStruct)structToExtend.Value); if (baseStructDefinition.PrototypeOnly) { RecordError(ErrorCode.CannotExtendPrototypeStruct, "Cannot extend struct '" + baseStructDefinition.Name + "' because it is only a prototype"); } structDefinition.Extends = baseStructDefinition; structDefinition.SizeInBytes = baseStructDefinition.SizeInBytes; structDefinition.Members.AddRange(baseStructDefinition.Members); if (!structDefinition.Modifiers.HasSameModifiers(baseStructDefinition.Modifiers)) { RecordError(ErrorCode.DifferentModifierInPrototype, "This struct has different modifiers to the base type"); } } } _source.ExpectKeyword(PredefinedSymbol.OpenBrace); while (!_source.NextIsKeyword(PredefinedSymbol.CloseBrace)) { Token token = _source.ReadNextToken(); if (token is ModifierToken) { _state.NextTokenModifiers.Add((ModifierToken)token); } else if (token.IsVariableType) { do { ParseAndAddMemberToStruct(token, structName, structDefinition, structName); }while (_source.NextIsKeyword(PredefinedSymbol.Comma)); _source.ExpectKeyword(PredefinedSymbol.Semicolon); _state.NextTokenModifiers.Clear(); } else { RecordError(ErrorCode.UnexpectedToken, "Unexpected " + token.Name); } } _source.ExpectKeyword(PredefinedSymbol.Semicolon); return(structDefinition); }
public void AddStruct(ScriptStruct newStruct) { _structs.Add(newStruct); }
private ScriptStruct ProcessStructDeclaration() { VerifyModifiersAgainstType(ModifierTargets.Struct); Modifiers prototypeModifiers = null; Token structName = _source.ReadNextToken(); if (structName.Defined) { if ((structName.Type == TokenType.StructType) && (structName.StructType.PrototypeOnly)) { prototypeModifiers = structName.StructType.Modifiers; } else { throw new CompilerMessage(ErrorCode.TokenAlreadyDefined, "Token '" + structName.Name + "' is already defined"); } } ScriptStruct structDefinition = new ScriptStruct(structName.Name); structDefinition.Modifiers = _state.NextTokenModifiers; structName.Define(TokenType.StructType, structDefinition); structName.IsVariableType = true; if (_state.IsModifierPresent(PredefinedSymbol.Managed)) { structDefinition.IsManaged = true; } _state.NextTokenModifiers = new Modifiers(); if (_source.NextIsKeyword(PredefinedSymbol.Semicolon)) { structDefinition.PrototypeOnly = true; return structDefinition; } if (prototypeModifiers != null) { if (!structDefinition.Modifiers.HasSameModifiers(prototypeModifiers)) { RecordError(ErrorCode.DifferentModifierInPrototype, "This struct has different modifiers to the prototype"); } } if (_source.NextIsKeyword(PredefinedSymbol.Extends)) { Token structToExtend = _source.ReadNextAsVariableType(); if (structToExtend.Type != TokenType.StructType) { RecordError(ErrorCode.StructNameExpected, "Struct name expected at '" + structToExtend.Name + "'"); } else { ScriptStruct baseStructDefinition = ((ScriptStruct)structToExtend.Value); if (baseStructDefinition.PrototypeOnly) { RecordError(ErrorCode.CannotExtendPrototypeStruct, "Cannot extend struct '" + baseStructDefinition.Name + "' because it is only a prototype"); } structDefinition.Extends = baseStructDefinition; structDefinition.SizeInBytes = baseStructDefinition.SizeInBytes; structDefinition.Members.AddRange(baseStructDefinition.Members); if (!structDefinition.Modifiers.HasSameModifiers(baseStructDefinition.Modifiers)) { RecordError(ErrorCode.DifferentModifierInPrototype, "This struct has different modifiers to the base type"); } } } _source.ExpectKeyword(PredefinedSymbol.OpenBrace); while (!_source.NextIsKeyword(PredefinedSymbol.CloseBrace)) { Token token = _source.ReadNextToken(); if (token is ModifierToken) { _state.NextTokenModifiers.Add((ModifierToken)token); } else if (token.IsVariableType) { do { ParseAndAddMemberToStruct(token, structName, structDefinition, structName); } while (_source.NextIsKeyword(PredefinedSymbol.Comma)); _source.ExpectKeyword(PredefinedSymbol.Semicolon); _state.NextTokenModifiers.Clear(); } else { RecordError(ErrorCode.UnexpectedToken, "Unexpected " + token.Name); } } _source.ExpectKeyword(PredefinedSymbol.Semicolon); return structDefinition; }