List <object> CreateSymbols(List <TokenExpression> tokens, bool GenerateAdditionalFunctions) { List <object> declarationOrder = new List <object>(); var classDefinitions = tokens.TokensWhere(TokenType.ClassDefinition).ToArray(); var functypeDeclarations = tokens.TokensWhere(TokenType.FunctypeDeclaration).ToArray(); //var globalDefinitions = tokens.TokensWhere(TokenType.VariableDeclaration); //var constDefinitions = tokens.TokensWhere(TokenType.ConstDeclaration); //var functionDeclarations = tokens.TokensWhere(TokenType.FunctionDeclaration); //create structs foreach (var token in classDefinitions) { string className = token.Subexpressions[1].Token.Value; var structInfo = Structs.Get(className); declarationOrder.Add(structInfo); } //create function/delegate foreach (var token in functypeDeclarations) { var functionNameToken = token.Subexpressions[2]; string funcTypeName = GetFunctionName(functionNameToken, null); if (token.Subexpressions[0].TokenType == TokenType.Delegate) { var delegateInfo = Delegates.Get(funcTypeName); declarationOrder.Add(delegateInfo); } else { var functype = Functypes.Get(funcTypeName); declarationOrder.Add(functype); } } //data types exist now - now create structs, functions, functypes, globals, constants foreach (var token in tokens) { switch (token.TokenType) { case TokenType.ClassDefinition: { string className = token.Subexpressions[1].Token.Value; var structInfo = this.Structs.Get(className); HashSet <string> memberNames = new HashSet <string>(); memberNames.AddRange(structInfo.Members.Names()); var entries = token.Subexpressions[2].Subexpressions; foreach (var entry0 in entries) { var entry = entry0.Subexpressions[0]; switch (entry.TokenType) { case TokenType.FunctionDeclaration: { Function function; var blockToken = entry0.GetFirstSubexpression(TokenType.Block); if (blockToken != null) { //create function, and add it to the list (gives it an index) function = CreateSymbolForFunction(entry, className, true); this.FunctionDefinitionTokens[function] = blockToken; declarationOrder.Add(function); } else { //declaration without a definition - don't add it to the list until it's actually defined function = CreateSymbolForFunction(entry, className, false); } var functionParameterList = entry.GetFirstSubexpression(TokenType.FunctionParameterList); bool hasAssignment = (functionParameterList.GetSubexpressionsRecursive(TokenType.Assign).FirstOrDefault() != null); if (hasAssignment) { this.FunctionDeclarationTokens[function] = entry; } } break; case TokenType.ConstDeclaration: { CreateSymbolForConst(entry, className); } break; case TokenType.VariableDeclaration: { var variables = GetVariablesInVariableDeclaration(entry); foreach (var variable in variables) { //does symbol already exist? if (variable.DataType != DataType.Void && memberNames.Contains(variable.Name)) { //do nothing } else { int index = structInfo.Members.Count; structInfo.Members.Add(variable); variable.Index = index; variable.Parent = structInfo; variable.Root = ainFile; memberNames.Add(variable.Name); } } } break; } } } break; case TokenType.FunctypeDeclaration: { var declarationToken = token.Subexpressions[0]; var dataTypeToken = token.Subexpressions[1]; var functionNameToken = token.Subexpressions[2]; var parameterListToken = token.Subexpressions[3]; var dataType = GetDataType(dataTypeToken); string functypeName = GetFunctionName(functionNameToken); FunctionType funcType; if (declarationToken.TokenType == TokenType.Delegate) { funcType = Delegates.Get(functypeName); } else { funcType = Functypes.Get(functypeName); } funcType.SetVariableType(dataType); int parameterNumber = 0; foreach (var parameterDataTypeToken in parameterListToken.Subexpressions) { int index = funcType.Parameters.Count; var parameter = GetDataType(parameterDataTypeToken); if (parameter.DataType != DataType.Void) { parameter.Name = parameterNumber.ToString(); parameter.Index = index; parameter.Root = ainFile; funcType.Parameters.Add(parameter); if (parameter.DataType.IsPrimitiveRefType()) { var voidParameter = new Variable("<void>", DataType.Void, 0, 0); voidParameter.Index = index + 1; voidParameter.Root = ainFile; funcType.Parameters.Add(voidParameter); } } parameterNumber++; } funcType.ParameterCount = funcType.Parameters.Count; } break; case TokenType.FunctionDeclaration: { var function = CreateSymbolForFunction(token); declarationOrder.Add(function); var blockToken = token.GetFirstSubexpression(TokenType.Block); if (blockToken != null) { this.FunctionDefinitionTokens[function] = blockToken; } var functionParameterList = token.GetFirstSubexpression(TokenType.FunctionParameterList); bool hasAssignment = (functionParameterList.GetSubexpressionsRecursive(TokenType.Assign).FirstOrDefault() != null); if (hasAssignment) { this.FunctionDeclarationTokens[function] = token; } } break; case TokenType.GlobalGroupDeclaration: { var groupNameToken = token.Subexpressions.FirstOrDefault(); string groupName = groupNameToken.Token.Value; int groupIndex = this.GlobalGroupNames.Add(groupName); foreach (var variableDeclarationToken in token.Subexpressions.TokensWhere(TokenType.VariableDeclaration)) { var variables = GetVariablesInVariableDeclaration(variableDeclarationToken); foreach (var variable in variables) { if (variable.Name == "<void>") { var global = new Global(); global.GroupIndex = groupIndex; global.Name = variable.Name; global.SetVariableType(variable); global.Index = Globals.List.Count; global.Root = ainFile; Globals.List.Add(global); } else { var global = Globals.Get(variable.Name); if (this.ArraySizeExpressions.ContainsKey(variable)) { this.ArraySizeExpressions[global] = this.ArraySizeExpressions[variable]; } global.SetVariableType(variable); global.GroupIndex = groupIndex; declarationOrder.Add(global); } } } } break; case TokenType.VariableDeclaration: { var variables = GetVariablesInVariableDeclaration(token); foreach (var variable in variables) { if (variable.Name == "<void>") { var global = new Global(); global.Name = variable.Name; global.SetVariableType(variable); global.Index = Globals.List.Count; global.Root = ainFile; Globals.List.Add(global); } else { var global = Globals.Get(variable.Name); declarationOrder.Add(global); if (this.ArraySizeExpressions.ContainsKey(variable)) { this.ArraySizeExpressions[global] = this.ArraySizeExpressions[variable]; } global.SetVariableType(variable); } } } break; case TokenType.ConstDeclaration: { CreateSymbolForConst(token); } break; case TokenType.Eof: { string fileName = token.Subexpressions[0].Token.Value; declarationOrder.Add(fileName); } break; case TokenType.HllDeclaration: { string libraryName = token.Subexpressions[0].Token.Value; CreateHllSymbols(token.Subexpressions, libraryName, libraryName); declarationOrder.Add(Libraries.Get(libraryName)); } break; } } Function zeroFunction = null; bool createZeroFunction = false; if (GenerateAdditionalFunctions) { createZeroFunction = !Functions.Contains("0"); zeroFunction = null; if (createZeroFunction) { zeroFunction = Functions.Get("0", false); declarationOrder.Add(zeroFunction); } } var declaraedStructs = declarationOrder.OfType <Struct>().OrderByIndex().ToArray(); foreach (var sturctInfo in declaraedStructs) { GenerateArrayInitializer(declarationOrder, sturctInfo, true, false); } if (GenerateAdditionalFunctions) { //create @2 functions for each constructor foreach (var structInfo in Structs.List) { GenerateArrayInitializer(declarationOrder, structInfo, false, false); } if (createZeroFunction) { //create 0 function zeroFunction = Functions.Get("0"); //wait until later to define it } this.FunctionDefinitionTokens[Functions.Get("NULL")] = new TokenExpression(TokenType.Block); declarationOrder.Add(ainFile.GetFunction("NULL")); } return(declarationOrder); }
internal Variable GetDataType(TokenExpression dataTypeToken) { bool isRef = false; bool isArray = false; int structType = -1; int arrayDimensions = 0; DataType dataType = DataType.Void; for (int i = 0; i < dataTypeToken.Subexpressions.Count; i++) { var token = dataTypeToken.Subexpressions[i]; switch (token.TokenType) { case TokenType.ArrayType: dataTypeToken = token; i = -1; continue; case TokenType.Ref: isRef = true; break; case TokenType.Array: isArray = true; //i++; arrayDimensions = 1; break; case TokenType.Number: arrayDimensions = token.Token.ToInt(); break; case TokenType.Void: dataType = DataType.Void; break; case TokenType.Int: dataType = DataType.Int; if (isArray) { dataType += 4; } if (isRef) { dataType += 8; } break; case TokenType.Struct: dataType = DataType.Struct; structType = -1; if (isArray) { dataType += 4; } if (isRef) { dataType += 8; } break; case TokenType.String: dataType = DataType.String; if (isArray) { dataType += 4; } if (isRef) { dataType += 8; } break; case TokenType.Float: dataType = DataType.Float; if (isArray) { dataType += 4; } if (isRef) { dataType += 8; } break; case TokenType.Bool: dataType = DataType.Bool; if (isArray && !isRef) { dataType += 3; } else if (!isArray && isRef) { dataType += 4; } else if (isArray && isRef) { dataType += 5; } break; case TokenType.Lint: dataType = DataType.Lint; if (isArray && !isRef) { dataType += 3; } else if (!isArray && isRef) { dataType += 4; } else if (isArray && isRef) { dataType += 5; } break; case TokenType.IMainSystem: dataType = DataType.IMainSystem; break; case TokenType.Identifier: string name = token.Token.Value; if (Structs.Contains(name)) { structType = Structs.NameToIndex[name]; dataType = DataType.Struct; if (isArray) { dataType += 4; } if (isRef) { dataType += 8; } } else if (Functypes.Contains(name)) { structType = Functypes.NameToIndex[name]; dataType = DataType.Functype; if (isArray && !isRef) { dataType += 3; } else if (!isArray && isRef) { dataType += 4; } else if (isArray && isRef) { dataType += 5; } } else if (Delegates.Contains(name)) { structType = Delegates.NameToIndex[name]; dataType = DataType.Delegate; if (isArray && !isRef) { dataType += 3; } else if (!isArray && isRef) { dataType += 4; } else if (isArray && isRef) { dataType += 5; } } else { //HLL data types if (name == "intp") { dataType = DataType.RefInt; } else if (name == "stringp") { dataType = DataType.RefString; } else if (name == "floatp") { dataType = DataType.RefFloat; } else if (name == "boolp") { dataType = DataType.RefBool; } else { //unknown data type dataType = DataType.Struct; if (isRef) { dataType = DataType.RefStruct; } structType = -1; } } break; } } return(new Variable("", dataType, structType, arrayDimensions)); }