public SplitExpression(Token splitOperator, Expression leftHandSide, Expression rightHandSide, Expression completeExpression) : base(completeExpression) { this.Operator = splitOperator; this.LeftHandSide = leftHandSide; this.RightHandSide = rightHandSide; }
private void ParseAndAddFunctionDefinition(Token variableType, Token variableName, bool isMemberFunction) { if (isMemberFunction) { VerifyModifiersAgainstType(ModifierTargets.MemberFunction); } else { VerifyModifiersAgainstType(ModifierTargets.GlobalFunction); } VerifyReturnTypeValidForFunction(variableType); ScriptFunction func = new ScriptFunction(variableType, variableName); ParseFunctionParameterList(func); if (_source.NextIsKeyword(PredefinedSymbol.Semicolon)) { func.IsPrototypeOnly = true; } else { if (func.IsPrototypeOnly == true) { throw new CompilerMessage(ErrorCode.AnonymousParameterInFunctionBody, "One or more parameters did not have a name"); } func.IsPrototypeOnly = false; _state.NextTokenModifiers.Clear(); ProcessFunctionBody(); } }
public Token Clone() { Token copy = new Token(_name); copy._defined = this._defined; copy._isVariableType = this._isVariableType; copy._isArray = this._isArray; copy._arraySize = this._arraySize; copy._type = this._type; copy._value = this._value; return copy; }
private void ProcessTokenAtTopLevel(Token thisToken) { if (thisToken is ModifierToken) { _state.NextTokenModifiers.Add((ModifierToken)thisToken); } else if (thisToken.IsVariableType) { bool wasFunction = false; do { wasFunction = ParseAndAddGlobalVariableOrFunction(thisToken); } while ((!wasFunction) && (_source.NextIsKeyword(PredefinedSymbol.Comma))); if (!wasFunction) { _source.ExpectKeyword(PredefinedSymbol.Semicolon); } _state.NextTokenModifiers.Clear(); } else if (thisToken is KeywordToken) { PredefinedSymbol keyword = ((KeywordToken)thisToken).SymbolType; if (keyword == PredefinedSymbol.StructDefinition) { _output.AddStruct(ProcessStructDeclaration()); } else if (keyword == PredefinedSymbol.Enum) { ProcessEnumDeclaration(); } else if (keyword == PredefinedSymbol.Export) { ProcessExportCommand(); } else { RecordError(ErrorCode.InvalidUseOfKeyword, "Invalid use of '" + thisToken.Name + "'"); } } else if (thisToken.Name.StartsWith(Constants.NEW_SCRIPT_MARKER)) { _scriptName = thisToken.Name.Substring(Constants.NEW_SCRIPT_MARKER.Length, thisToken.Name.Length - Constants.NEW_SCRIPT_MARKER.Length - 1); } else { RecordError(ErrorCode.UnexpectedToken, "Unexpected '" + thisToken.Name + "'"); } }
public static void SetArrayPropertiesOnTokenFromStream(ScriptReader source, Token variableName) { if (source.NextIsKeyword(PredefinedSymbol.OpenSquareBracket)) { variableName.IsArray = true; if (source.NextIsKeyword(PredefinedSymbol.CloseSquareBracket)) { variableName.ArraySize = Token.ARRAY_SIZE_DYNAMIC; } else { variableName.ArraySize = source.ReadNextAsConstInt(); source.ExpectKeyword(PredefinedSymbol.CloseSquareBracket); } } }
private void DeclareLocalVariable(Token variableType) { _source.IgnoreAsteriskIfPresent(); Token variableName = _source.ReadNextTokenAndThrowIfAlreadyDefined(); CompilerUtils.SetArrayPropertiesOnTokenFromStream(_source, variableName); CompilerUtils.VerifyModifiersAgainstType(ModifierTargets.LocalVariable, _state.NextTokenModifiers); /* TODO: get this working ScriptVariable newVariable = ProcessVariableDeclaration(variableType, _output.GlobalData, null, _state.NextTokenModifiers); variableName.Define(TokenType.LocalVariable, newVariable); */ if (_source.NextIsKeyword(PredefinedSymbol.SetEqual)) { Expression setEqualTo = ReadExpression(false, PredefinedSymbol.Semicolon, PredefinedSymbol.Comma); // TODO: check types, assign result to variable } }
public static bool AdjustBracketLevelIfTokenIsBracket(Token token, ref int bracketLevel) { if (token is KeywordToken) { PredefinedSymbol symbol = ((KeywordToken)token).SymbolType; if ((symbol == PredefinedSymbol.OpenBrace) || (symbol == PredefinedSymbol.OpenParenthesis) || (symbol == PredefinedSymbol.OpenSquareBracket)) { bracketLevel++; return true; } else if ((symbol == PredefinedSymbol.CloseBrace) || (symbol == PredefinedSymbol.CloseParenthesis) || (symbol == PredefinedSymbol.CloseSquareBracket)) { bracketLevel--; return true; } } return false; }
public bool HasNonImportedMemberOfType(Token tokenToLookFor) { foreach (ScriptVariable member in Members) { if (member.VariableTypeToken == tokenToLookFor) { bool thisOneIsOk = true; if ((member is FixedOffsetVariable) && (((FixedOffsetVariable)member).IsAttributeProperty)) { thisOneIsOk = false; } if (thisOneIsOk) { return true; } } } return false; }
public static Token GetTokenForStructMember(TokenizedScript script, Token structName, Token memberName, out string mangledName) { mangledName = structName.Name + "::" + memberName.Name; return script.FindTokenWithName(mangledName); }
private void VerifyReturnTypeValidForFunction(Token returnType) { if (returnType.Type == TokenType.StructType) { if (!returnType.StructType.IsManaged) { throw new CompilerMessage(ErrorCode.CannotReturnStructFromFunction, "Cannot return a non-managed struct from a function"); } } }
public void AddToken(Token tokenToAdd) { _tokens.Add(tokenToAdd.Name, tokenToAdd); }
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 void VerifyParameterTypeValidForFunction(Token parameterType) { if (parameterType.Type == TokenType.StructType) { if (!parameterType.StructType.IsManaged) { throw new CompilerMessage(ErrorCode.CannotPassStructToFunction, "Cannot pass a non-managed struct to a function"); } } }
private bool ParseAndAddGlobalVariableOrFunction(Token variableType) { bool isMemberFunctionBody = false; _source.IgnoreAsteriskIfPresent(); FixedOffsetVariable importedVersion = null; Token variableName = _source.ReadNextToken(); if ((variableName.Type == TokenType.GlobalVariable) && (variableName.Variable.IsImported) && (!variableName.Variable.IsAccessed)) { importedVersion = variableName.Variable; } else { ReadNameOfNewGlobalVariableOrFunction(variableName, out isMemberFunctionBody); } if (_source.NextIsKeyword(PredefinedSymbol.OpenParenthesis)) { ParseAndAddFunctionDefinition(variableType, variableName, isMemberFunctionBody); return true; } else { CompilerUtils.SetArrayPropertiesOnTokenFromStream(_source, variableName); ParseAndAddGlobalVariableDefinition(variableType, variableName, importedVersion); } return false; }
private void ParseAndAddGlobalVariableDefinition(Token variableType, Token variableName, FixedOffsetVariable importedVersion) { VerifyModifiersAgainstType(ModifierTargets.GlobalVariable); FixedOffsetVariable newVariable = ProcessVariableDeclaration(variableType, _output.GlobalData, null, _state.NextTokenModifiers); variableName.Define(TokenType.GlobalVariable, newVariable); if (_source.NextIsKeyword(PredefinedSymbol.SetEqual)) { // TODO: Check types to ensure this is valid newVariable.DefaultValue = _source.ReadNextAsConstInt(); } if (importedVersion != null) { if (importedVersion.CompareTo(newVariable) != 0) { throw new CompilerMessage(ErrorCode.NewDefinitionIsDifferent, "New definition of '" + variableName.Name + "' does not match previous one"); } } }
private void ReadNameOfNewGlobalVariableOrFunction(Token variableName, out bool isMemberFunctionBody) { isMemberFunctionBody = false; if (variableName.Type == TokenType.StructType) { // Defining the body of a member function, eg. function Struct::function() _source.ExpectKeyword(PredefinedSymbol.MemberOf); Token memberName = _source.ReadNextToken(); string mangledName; Token memberFunc = GetTokenForStructMember(variableName, memberName, out mangledName); if (memberFunc == null) { throw new CompilerMessage(ErrorCode.MemberFunctionNotDefined, "Struct '" + variableName.Name + "' has no member function '" + memberName.Name + "'"); } // TODO: Verify that memberFunc is a function not a variable // TODO: Verify that function arguments match prototype variableName = memberFunc; isMemberFunctionBody = true; } else if (variableName.Defined) { throw new CompilerMessage(ErrorCode.TokenAlreadyDefined, "Token '" + variableName.Name + "' is already defined"); } }
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; }
public ScriptFunction(Token returnType, Token name) { ReturnType = returnType; Name = name; Parameters = new List<FunctionParameter>(); }
public FunctionParameter(Token type, Token name) { Type = type; Name = name; }
private Token GetTokenForStructMember(Token structName, Token memberName, out string mangledName) { return CompilerUtils.GetTokenForStructMember(_tokenizedScript, structName, memberName, out mangledName); }