/// <summary> /// <summary> /// Compute the typed proper paths of a data defintion. The proper root paths are /// root procedures path and data definition variables path. /// </summary> /// <param name="dataNode">The node owning the data dedinition.</param> /// <param name="dataDesc">The Data Description to compute the proper root path</param> /// <param name="properType"> The Proper type of the data definition </param> /// <param name="pathProcedures">[out] root procedures path</param> /// <param name="pathVariables">[out]typed variables path</param> public static void ComputeTypedProperPaths(Node dataNode, DataDescriptionEntry dataDesc, Compiler.Nodes.TypeDefinition properType, out List <string> pathProcedures, out List <Tuple <string, string> > pathVariables) { System.Diagnostics.Contracts.Contract.Requires(properType != null); pathProcedures = new List <string>(); pathVariables = new List <Tuple <string, string> >(); if (properType == null) { return; } pathVariables.Add(new Tuple <string, string>(dataDesc.Name, properType.Name)); Compiler.Nodes.Node parent = dataNode.Parent; while (parent != null) { if (parent is TypeCobol.Compiler.Nodes.DataDefinition) { TypeCobol.Compiler.Nodes.DataDefinition dataParent = parent as TypeCobol.Compiler.Nodes.DataDefinition; pathVariables.Add(new System.Tuple <string, string>(dataParent.Name, "")); } else if (!string.IsNullOrEmpty(parent.Name)) { pathProcedures.Add(parent.Name); } parent = parent.Parent; } }
/// <summary> /// <summary> /// Compute the proper paths of a data defintion. The proper root paths are /// root procedures path and data definition variables path. /// </summary> /// <param name="dataDef">The Data Definition to compute the proper root path</param> /// <param name="pathProcedures">[out] root procedures path</param> /// <param name="pathVariables">[out]variables path</param> public static void ComputeProperPaths(TypeCobol.Compiler.Nodes.DataDefinition dataDef, out List <string> pathProcedures, out List <string> pathVariables) { pathProcedures = new List <string>(); pathVariables = new List <string>(); pathVariables.Add(dataDef.Name); var parent = dataDef.Parent; while (parent != null) { if (!(parent is TypeCobol.Compiler.Nodes.DataDefinition)) { if (!string.IsNullOrEmpty(parent.Name)) { pathProcedures.Add(parent.Name); } } else { pathVariables.Add(parent.Name); } parent = parent.Parent; } pathProcedures.Reverse(); pathVariables.Reverse(); }
/// <summary> /// Determine if a Data Definition is included a TypeDefintion /// </summary> /// <param name="dataDef">The Data Definition to check</param> /// <returns>true if the DataDefintion is included in a TypeDefinition, false otherwise</returns> internal bool IsTypeDefinition(TypeCobol.Compiler.Nodes.DataDefinition dataDef) { while (dataDef != null) { if (dataDef is TypeCobol.Compiler.Nodes.TypeDefinition) { return(true); } dataDef = dataDef.Parent as TypeCobol.Compiler.Nodes.DataDefinition; } return(false); }
internal static List<ITextLine> CreateDataDefinition(SymbolTable table, ColumnsLayout? layout, List<string> rootProcedures, List< Tuple<string,string> > rootVariableName, TypeCobol.Compiler.Nodes.DataDefinition ownerDefinition, DataDefinitionEntry data_def, int level, int indent, bool isCustomType, bool isFirst, TypeDefinition customtype = null) { var data = data_def as DataDescriptionEntry; if (data != null) { bool bHasPeriod = false; var line = GetIndent(level, indent, isFirst); line.Append(level.ToString("00")); if (!isCustomType) { bool bHasDependingOn = false; bool bHasIndexes = false; List<string> dependingOnAccessPath = null; Dictionary<Compiler.Scanner.Token, string> indexesMap = null; PreGenDependingOnAndIndexed(table, rootProcedures, rootVariableName, ownerDefinition, data_def, out bHasDependingOn, out bHasIndexes, out dependingOnAccessPath, out indexesMap); bool globalSeen = false; string text = !(bHasDependingOn || bHasIndexes) ? ExtractPicTokensValues(layout, data, out bHasPeriod, out globalSeen) : ""; if (text.Length > 0) { AppendNameAndGlobalDataDef(line, data_def, globalSeen); line.Append(text); } else if (!(bHasDependingOn || bHasIndexes) && data.Picture != null && !string.IsNullOrEmpty(data.Picture.ToString())) { AppendNameAndGlobalDataDef(line, data_def, globalSeen); line.Append(" PIC ").Append(data.Picture); } else {//Try to extract after a Level. Func<Compiler.Scanner.Token, string> depenOnTokenFilter = null; Func<Compiler.Scanner.Token, string> indexedByTokenFilter = null; PostGenDependingOnAndIndexed(ownerDefinition, data_def, bHasDependingOn, bHasIndexes, dependingOnAccessPath, indexesMap, out depenOnTokenFilter, out indexedByTokenFilter); text = ExtractTokensValuesAfterLevel(layout, data, out bHasPeriod, bHasDependingOn ? depenOnTokenFilter : indexedByTokenFilter); if (text.Length > 0) { line.Append(text); } else { AppendNameAndGlobalDataDef(line, data_def, globalSeen); } } } else if (customtype != null) { //This variable will have no subtypes as children at all //So Auto detect a type based on scalar COBOL typedef. bool bHasDependingOn = false; bool bHasIndexes = false; List<string> dependingOnAccessPath = null; Dictionary<Compiler.Scanner.Token, string> indexesMap = null; PreGenDependingOnAndIndexed(table, rootProcedures, rootVariableName, ownerDefinition, data_def, out bHasDependingOn, out bHasIndexes, out dependingOnAccessPath, out indexesMap); string text = !(bHasDependingOn || bHasIndexes) ? ExtractAnyCobolScalarTypeDef(layout, customtype, out bHasPeriod, false) : ""; if (text.Length != 0) { AppendNameAndGlobalDataDef(line, data_def, false); line.Append(text); } else { Func<Compiler.Scanner.Token, string> depenOnTokenFilter = null; Func<Compiler.Scanner.Token, string> indexedByTokenFilter = null; PostGenDependingOnAndIndexed(ownerDefinition, data_def, bHasDependingOn, bHasIndexes, dependingOnAccessPath, indexesMap, out depenOnTokenFilter, out indexedByTokenFilter); bool globalSeen = false; text = ExtractTokensValuesAfterTypeName(layout, data, out bHasPeriod, out globalSeen, bHasDependingOn ? depenOnTokenFilter : indexedByTokenFilter); AppendNameAndGlobalDataDef(line, data_def, globalSeen); if (text.Length != 0) line.Append(text); } } else { AppendNameAndGlobalDataDef(line, data_def, false); } if (!bHasPeriod) { line.Append('.'); } return LineToTextLines(line.ToString()); } else if (data_def is DataConditionEntry || data_def is DataRenamesEntry || data_def is DataRedefinesEntry) { bool bHasPeriod = false; var line = GetIndent(level, indent, isFirst); string text = ConsumedTokenToString(layout, data_def, out bHasPeriod); line.Append(text); if (!bHasPeriod) { line.Append('.'); } return LineToTextLines(line.ToString()); } else {//Humm ... It will be a Bug System.Diagnostics.Debug.Assert(data_def is DataDescriptionEntry || data_def is DataConditionEntry); } return null; }
/// <summary> /// Post generation calculation of data definition having depending on or indexed variables. /// </summary> /// <param name="ownerDefinition">The Owner of the current definition</param> /// <param name="data_def">The current definition</param> /// <param name="bHasDependingOn">true if the current variable hace depending on variables, false otherwise</param> /// <param name="bHasIndexes">true if the current variable definition have indexed variables, fals eotherwise.</param> /// <param name="dependingOnAccessPath">Depending on variables access path list</param> /// <param name="indexesMap">Indexed variable map to tokens</param> internal static void PostGenDependingOnAndIndexed(TypeCobol.Compiler.Nodes.DataDefinition ownerDefinition, DataDefinitionEntry data_def, bool bHasDependingOn, bool bHasIndexes, List<string> dependingOnAccessPath, Dictionary<Compiler.Scanner.Token, string> indexesMap, out Func<Compiler.Scanner.Token, string> depenOnTokenFilter, out Func<Compiler.Scanner.Token, string> indexedByTokenFilter ) { var data = data_def as DataDescriptionEntry; depenOnTokenFilter = null; indexedByTokenFilter = null; if (bHasIndexes) { indexedByTokenFilter = (token) => { return indexesMap.ContainsKey(token) ? indexesMap[token] : token.Text; }; } if (bHasDependingOn) { if (data != null && !data.OccursDependingOn.MainSymbolReference.IsQualifiedReference) depenOnTokenFilter = (token) => { if (bHasIndexes) { if (indexesMap.ContainsKey(token)) return indexesMap[token]; } if (token == data.OccursDependingOn.MainSymbolReference.NameLiteral.Token) { return string.Join(" OF ", dependingOnAccessPath.ToArray()); } else { return token.Text; } }; else { //We have an incomplete qualification to the root variable depenOnTokenFilter = (token) => { if (bHasIndexes) { if (indexesMap.ContainsKey(token)) return indexesMap[token]; } QualifiedSymbolReference qualSymRef = (QualifiedSymbolReference)data?.OccursDependingOn.MainSymbolReference; if (qualSymRef != null && qualSymRef.IsTypeCobolQualifiedReference) { DataDescription dataDescription = ownerDefinition as DataDescription; if (dataDescription?.QualifiedTokenSubsitutionMap != null && dataDescription.QualifiedTokenSubsitutionMap.ContainsKey(token)) { if (token == qualSymRef.Head.NameLiteral.Token) return dataDescription.QualifiedTokenSubsitutionMap[token] + " OF " + string.Join(" OF ", dependingOnAccessPath.ToArray()); else return dataDescription.QualifiedTokenSubsitutionMap[token]; } else { return token.Text; } } else { //Pure Cobol85 Qualification add left qualification to the root if (qualSymRef != null && token == qualSymRef.Tail.NameLiteral.Token) { return token.Text + " OF " + string.Join(" OF ", dependingOnAccessPath.ToArray()); } else { return token.Text; } } }; } } }
/// <summary> /// Pre Generation calculation for collection variable path access and index variable map. /// </summary> /// <param name="table">The Current Symbol Table</param> /// <param name="rootProcedures">Root procedures</param> /// <param name="rootVariableName">All current root variable</param> /// <param name="ownerDefinition">The Owner of the current definition</param> /// <param name="data_def">The current definition</param> /// <param name="bHasDependingOn">[out] true if the current variable hace depending on variables, false otherwise</param> /// <param name="bHasIndexes">[out] true if the current variable definition have indexed variables, fals eotherwise.</param> /// <param name="dependingOnAccessPath">[out] depending on variables access path list</param> /// <param name="indexesMap">[out] Indexed variable map to tokens</param> internal static void PreGenDependingOnAndIndexed(SymbolTable table, List<string> rootProcedures, List<Tuple<string, string>> rootVariableName, TypeCobol.Compiler.Nodes.DataDefinition ownerDefinition, DataDefinitionEntry data_def, out bool bHasDependingOn, out bool bHasIndexes, out List<string> dependingOnAccessPath, out Dictionary<Compiler.Scanner.Token, string> indexesMap ) { var data = data_def as DataDescriptionEntry; bHasDependingOn = false; bHasIndexes = false; dependingOnAccessPath = null; indexesMap = null; if (data?.OccursDependingOn != null) { if (!data.OccursDependingOn.MainSymbolReference.IsQualifiedReference) { dependingOnAccessPath = new List<string>(); if (LookupAccessPathForName(table, ownerDefinition, data.OccursDependingOn.MainSymbolReference.Name.ToLower(), dependingOnAccessPath)) { //Remove the Type name dependingOnAccessPath.RemoveAt(0); dependingOnAccessPath.Reverse(); dependingOnAccessPath.AddRange(rootVariableName.ConvertAll<string>(vt => vt.Item1)); bHasDependingOn = true; } } else { dependingOnAccessPath = new List<string>(); QualifiedSymbolReference qualSymRef = (QualifiedSymbolReference)data.OccursDependingOn.MainSymbolReference; string tailName = qualSymRef.Tail.Name; if (LookupAccessPathForName(table, ownerDefinition, tailName.ToLower(), dependingOnAccessPath)) { //Remove the type name dependingOnAccessPath.RemoveAt(0); //Remove the variable dependingOnAccessPath.RemoveAt(dependingOnAccessPath.Count - 1); if (dependingOnAccessPath.Count > 0) { dependingOnAccessPath.Reverse(); dependingOnAccessPath.AddRange(rootVariableName.ConvertAll<string>(vt => vt.Item1)); bHasDependingOn = true; } } } } if (data?.Indexes != null) { bHasIndexes = true; //So Children of the owner definition contains all indexes indexesMap = BuiltIndexMap(rootProcedures, rootVariableName, data.Indexes, ownerDefinition); } }
/// <summary> /// Build the Dictionary that associate a token of an index-name-1 to its hash + name. /// </summary> /// <param name="indexes">The Array of Index Symbol Definition</param> /// <param name="ownerDefinition">The Owner of the definition that contains the INDEXED BY clause</param> /// <returns>The Dictionary</returns> private static Dictionary<Compiler.Scanner.Token, string> BuiltIndexMap(List<string> rootProcedures, List<Tuple<string, string>> rootVariableName, SymbolDefinition[] indexes, TypeCobol.Compiler.Nodes.DataDefinition ownerDefinition) { Dictionary<Compiler.Scanner.Token, string> map = new Dictionary<Compiler.Scanner.Token, string>(indexes.Length); List<string> pathProcedures; List<string> pathVariables; GeneratorHelper.ComputeProperPaths(ownerDefinition, out pathProcedures, out pathVariables); List<string> list_items = new List<string>(); //list_items.AddRange(pathProcedures); //Add root procedures for (int j = rootProcedures.Count - 1; j >= 0; j--) { list_items.Add(rootProcedures[j]); } //Add Root variables for (int j = rootVariableName.Count - 1; j >= 0; j--) { list_items.Add(rootVariableName[j].Item1); if (j != 0 && rootVariableName[j].Item2 != null && rootVariableName[j].Item2.Trim().Length > 0) list_items.Add(rootVariableName[j].Item2); } list_items.AddRange(pathVariables); string qn = string.Join(".", list_items.ToArray()); foreach (Node child in ownerDefinition.Children) { if (child is IndexDefinition) { IndexDefinition index = child as IndexDefinition; foreach (SymbolDefinition sym in indexes) { if (sym.Name.Equals(index.Name)) { string qualified_name = qn + '.' + index.Name; string hash_name = GeneratorHelper.ComputeIndexHashName(qualified_name, ownerDefinition); map[sym.NameLiteral.Token] = hash_name; } } } } return map; }
/// <summary> /// Build the Dictionary that associate a token of an index-name-1 to its hash + name. /// </summary> /// <param name="indexes">The Array of Index Symbol Definition</param> /// <param name="ownerDefinition">The Owner of the definition that contains the INDEXED BY clause</param> /// <returns>The Dictionary</returns> private static Dictionary <Compiler.Scanner.Token, string> BuiltIndexMap(Node rootNode, List <string> rootProcedures, List <Tuple <string, string> > rootVariableName, SymbolDefinition[] indexes, TypeCobol.Compiler.Nodes.DataDefinition ownerDefinition) { Dictionary <Compiler.Scanner.Token, string> map = new Dictionary <Compiler.Scanner.Token, string>(indexes.Length); List <string> pathProcedures; List <string> pathVariables; GeneratorHelper.ComputeProperPaths(ownerDefinition, out pathProcedures, out pathVariables); List <string> list_items = new List <string>(); //list_items.AddRange(pathProcedures); //Add root procedures for (int j = rootProcedures.Count - 1; j >= 0; j--) { list_items.Add(rootProcedures[j]); } //Add Root variables for (int j = rootVariableName.Count - 1; j >= 0; j--) { list_items.Add(rootVariableName[j].Item1); if (j != 0 && rootVariableName[j].Item2 != null && rootVariableName[j].Item2.Trim().Length > 0) { list_items.Add(rootVariableName[j].Item2); } } list_items.AddRange(pathVariables); string qn = string.Join(".", list_items.ToArray()); AddIndexMap(rootNode, rootNode.QualifiedName.ToString(), indexes, map); AddIndexMap(ownerDefinition, qn, indexes, map); return(map); }