/// <summary> /// Retrieve the consumed Token as a String /// </summary> /// <param name="data_def">The DataDefintion to Retrieve the consumed Tokens.</param> /// <param name="bHasPeriod">out true if a period separator has been encountered, false otherwise.</param> /// <returns>The string representing the DataDefinition</returns> internal static string ConsumedTokenToString(DataDefinitionEntry data_def, out bool bHasPeriod) { bHasPeriod = false; StringBuilder sb = new StringBuilder(); if (data_def.ConsumedTokens != null) { if (data_def.ConsumedTokens != null) { int i = 0; while (i < data_def.ConsumedTokens.Count) { if ((i != data_def.ConsumedTokens.Count - 1) || (data_def.ConsumedTokens[i].TokenType != Compiler.Scanner.TokenType.PeriodSeparator)) { sb.Append(string.Intern(" "));//Add a space but not before a a Period Separator } sb.Append(data_def.ConsumedTokens[i].Text); if (i == data_def.ConsumedTokens.Count - 1) { bHasPeriod = data_def.ConsumedTokens[i].TokenType == Compiler.Scanner.TokenType.PeriodSeparator; } i++; } } } return(sb.ToString()); }
internal static void AddError(CodeElement e, string message, DataDefinitionEntry data, string rulestack = null, MessageCode code = MessageCode.SyntaxErrorInParser) { if (e.Diagnostics == null) { e.Diagnostics = new List <Diagnostic>(); } var parserDiag = new ParserDiagnostic(message, data.DataName.NameLiteral.Token, rulestack, code); e.Diagnostics.Add(parserDiag); }
/// <summary> /// Retrieve the consumed Token as a String /// </summary> /// <param name="data_def">The DataDefintion to Retrieve the consumed Tokens.</param> /// <param name="bHasPeriod">out true if a period separator has been encountered, false otherwise.</param> /// <returns>The string representing the DataDefinition</returns> internal static string ConsumedTokenToString(ColumnsLayout? layout, DataDefinitionEntry data_def, out bool bHasPeriod) { bHasPeriod = false; StringBuilder sb = new StringBuilder(); if (data_def.ConsumedTokens != null) { FlushConsumedTokens(layout, -1, data_def.ConsumedTokens, sb, out bHasPeriod); } return sb.ToString(); }
internal static ITextLine CreateDataDefinition(DataDefinitionEntry data_def, int level, int indent, bool isCustomType, bool isFirst, TypeDefinition customtype = null) { if (data_def is DataDescriptionEntry) { DataDescriptionEntry data = data_def as DataDescriptionEntry; bool bHasPeriod = false; var line = GetIndent(level, indent, isFirst); line.Append(level.ToString("00")); if (data_def.Name != null) { line.Append(' ').Append(data.Name); } if (!isCustomType) { string text = ExtractPicTokensValues(data, out bHasPeriod); if (text.Length > 0) { line.Append(text); } else { line.Append(" PIC ").Append(data.Picture); } } else if (customtype != null) { //This variable will have no subtypes as children at all //So Auto detect a type based on scalar COBOL typedef. string text = ExtractAnyCobolScalarTypeDef(customtype, out bHasPeriod); line.Append(text); } if (!bHasPeriod) { line.Append('.'); } return(new TextLineSnapshot(-1, line.ToString(), null)); } 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(data_def, out bHasPeriod); line.Append(text); if (!bHasPeriod) { line.Append('.'); } return(new TextLineSnapshot(-1, line.ToString(), null)); } else {//Humm ... It will be a Bug System.Diagnostics.Debug.Assert(data_def is DataDescriptionEntry || data_def is DataConditionEntry); } return(null); }
internal static void AddError(Node node, string message, DataDefinitionEntry data, MessageCode code = MessageCode.SyntaxErrorInParser) { ParserDiagnostic diagnostic; if (data?.DataName != null) { diagnostic = new ParserDiagnostic(message, data?.DataName != null ? data.DataName.NameLiteral.Token : data.ConsumedTokens[0], null, code); node.AddDiagnostic(diagnostic); } else { AddError(node, message, code); } }
/// <summary> /// Retrieve the consumed Token as a String /// </summary> /// <param name="data_def">The DataDefintion to Retrieve the consumed Tokens.</param> /// <param name="bHasPeriod">out true if a period separator has been encountered, false otherwise.</param> /// <returns>The string representing the DataDefinition</returns> internal static string ConsumedTokenToString(DataDefinitionEntry data_def, out bool bHasPeriod) { bHasPeriod = false; StringBuilder sb = new StringBuilder(); if (data_def.ConsumedTokens != null) { if (data_def.ConsumedTokens != null) { FlushConsumedTokens(0, data_def.ConsumedTokens, sb, out bHasPeriod); } } return(sb.ToString()); }
/// <summary> /// Append in the given StringBuilder the name and any global attribute of the the given DataDefition object. /// </summary> /// <param name="buffer">The String Buffer</param> /// <param name="dataDef">The Data Definition object</param> /// <param name="globalSeen">Global token hass been already seen</param> internal static void AppendNameAndGlobalDataDef(StringBuilder buffer, DataDefinitionEntry dataDef, bool globalSeen) { if (dataDef.Name != null) { buffer.Append(' ').Append(dataDef.Name); if (!globalSeen) { if (dataDef is CommonDataDescriptionAndDataRedefines) { CommonDataDescriptionAndDataRedefines cdadr = dataDef as CommonDataDescriptionAndDataRedefines; if (cdadr.IsGlobal) { Token gtoken = GetToken(dataDef.ConsumedTokens, TokenType.GLOBAL); buffer.Append(' ').Append(gtoken.Text); } } } } }
protected DataDefinition(DataDefinitionEntry entry) : base(entry) { }
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); } }
public virtual bool Visit(DataDefinitionEntry dataDefinitionEntry) { return(true); }
protected DataDefinition(DataDefinitionEntry entry) : base(entry) { References = new List <DataDefinition>(); }
public override bool Visit(DataDefinition dataDefinition) { CommonDataDescriptionAndDataRedefines commonDataDataDefinitionCodeElement = dataDefinition.CodeElement as CommonDataDescriptionAndDataRedefines; if (commonDataDataDefinitionCodeElement != null) { CheckPicture(dataDefinition); } DataDefinitionEntry dataDefinitionEntry = dataDefinition.CodeElement as DataDefinitionEntry; if (dataDefinitionEntry == null) { return(true); } var levelNumber = dataDefinitionEntry.LevelNumber; if (levelNumber != null) { var dataDefinitionParent = (dataDefinition.Parent as DataDefinition); var levelNumberValue = levelNumber.Value; if (dataDefinitionParent != null) { //Check if DataDefinition is level 88 and declared under a Type BOOL variable if (dataDefinitionParent.DataType == DataType.Boolean && levelNumberValue == 88) { DiagnosticUtils.AddError(dataDefinition.CodeElement, "The Level 88 symbol '" + dataDefinition.Name + "' cannot be declared under a BOOL typed symbol"); } } else { //Parent is not a DataDefinition so it's a top level data definition under a section (eg working-storage) //These top level DataDefinition can only be level 01 or 77 if (!(levelNumberValue == 01 || levelNumberValue == 77)) { DiagnosticUtils.AddError(dataDefinition.CodeElement, "The variable '" + dataDefinition.Name + "' can only be of level 01 or 77", dataDefinitionEntry); } } //Level 88 and 66 cannot have Children. if ((levelNumberValue == 88 || levelNumberValue == 66)) { if (dataDefinition.ChildrenCount != 0) { DiagnosticUtils.AddError(dataDefinition.CodeElement, "The variable '" + dataDefinition.Name + "' with level 88 and 66 cannot be group item.", dataDefinitionEntry); } if (dataDefinition.Usage != null) { DiagnosticUtils.AddError(dataDefinition.CodeElement, "The variable '" + dataDefinition.Name + "' with level 88 and 66 cannot have USAGE.", dataDefinitionEntry); } } } if (HasChildrenThatDeclareData(dataDefinition)) { if (dataDefinition.Picture != null) { DiagnosticUtils.AddError(dataDefinition, "Group item " + dataDefinition.Name + " cannot have a \"PICTURE\"", dataDefinitionEntry); } if (commonDataDataDefinitionCodeElement?.UserDefinedDataType != null) { DiagnosticUtils.AddError(dataDefinition, "Group item " + dataDefinition.Name + " cannot have a \"TYPE\"", dataDefinitionEntry); } if (commonDataDataDefinitionCodeElement?.IsBlankWhenZero?.Value == true) { DiagnosticUtils.AddError(dataDefinition, "Group itm " + dataDefinition.Name + " cannot have \"Blank when zero\" clause", dataDefinitionEntry); } return(true); } return(true); }