private void CheckNoGlobalOrExternal(DataDivision node) { if (node == null) { return; // no DATA DIVISION } foreach (var section in node.Children()) // "storage" sections { foreach (var child in section.Children) { var data = child.CodeElement as DataDescriptionEntry; if (data == null) { continue; } if (data.IsGlobal) // TCRFUN_DECLARATION_NO_GLOBAL { DiagnosticUtils.AddError(data, "Illegal GLOBAL clause in function data item."); } if (data.IsExternal) // TCRFUN_DECLARATION_NO_EXTERNAL { DiagnosticUtils.AddError(data, "Illegal EXTERNAL clause in function data item."); } } } }
public void OnNode([NotNull] Node node, ParserRuleContext context, CodeModel.Program program) { var functionDeclaration = node as FunctionDeclaration; if (functionDeclaration == null) { return; //not my job } var header = node.CodeElement as FunctionDeclarationHeader; if (header == null) { return; //not my job } var filesection = node.Get <FileSection>("file"); if (filesection != null) // TCRFUN_DECLARATION_NO_FILE_SECTION { DiagnosticUtils.AddError(filesection, "Illegal FILE SECTION in function \"" + header.Name + "\" declaration", context); } CheckNoGlobalOrExternal(node.Get <DataDivision>("data-division")); CheckNoLinkageItemIsAParameter(node.Get <LinkageSection>("linkage"), header.Profile); }
public static void OnNode(FunctionDeclaration functionDeclaration) { var header = functionDeclaration?.CodeElement as FunctionDeclarationHeader; if (header == null) { return; //not my job } var filesection = functionDeclaration.Get <FileSection>("file"); if (filesection != null) // TCRFUN_DECLARATION_NO_FILE_SECTION { DiagnosticUtils.AddError(filesection, "Illegal FILE SECTION in function \"" + header.Name + "\" declaration"); } CheckNoGlobalOrExternal(functionDeclaration.Get <DataDivision>("data-division")); CheckNoLinkageItemIsAParameter(functionDeclaration.Get <LinkageSection>("linkage"), header.Profile); CheckParameters(header.Profile, functionDeclaration); CheckNoPerform(functionDeclaration.SymbolTable.EnclosingScope, functionDeclaration); var headerNameURI = new URI(header.Name); var functions = functionDeclaration.SymbolTable.GetFunction(headerNameURI, functionDeclaration.Profile); if (functions.Count > 1) { DiagnosticUtils.AddError(functionDeclaration, "A function \"" + headerNameURI.Head + "\" with the same profile already exists in namespace \"" + headerNameURI.Tail + "\"."); } }
public void OnCodeElement(CodeElement e, ParserRuleContext ctxt) { var statement = e as CancelStatement; if (statement == null) { return; //not our job } var context = ctxt as CodeElementsParser.CancelStatementContext; foreach (var item in statement.Programs) { if (item == null) { continue; //TODO#249 } if (item.SymbolReference == null) { continue; // DO nothing } if (string.IsNullOrWhiteSpace(item.SymbolReference.Name) || item.SymbolReference.Name.IsNumeric()) { // we should link this error to the specific context.identifierOrLiteral[i] context // corresponding to statement.Items[i], but since refactor in #157 it's not trivial anymore DiagnosticUtils.AddError(statement, "CANCEL: <program name> must be alphanumeric", context); } } }
public void OnCodeElement(CodeElement e, ParserRuleContext c) { var data = e as DataRenamesEntry; if (data == null) { return; //not our job } var context = c as CodeElementsParser.DataConditionEntryContext; if (data.LevelNumber.Value != 66) { //(source page 379 of ISO Cobol 2014) DiagnosticUtils.AddError(data, "RENAMES must be level 66", context.levelNumber); } if (data.DataName == null) { //(source page 379 of ISO Cobol 2014) DiagnosticUtils.AddError(data, "Data name must be specified for level-66 items", context.levelNumber); } if (data.RenamesFromDataName.Equals(data.RenamesToDataName)) { //(source page 379 of ISO Cobol 2014) DiagnosticUtils.AddError(data, "Renamed items can't be the same " + data.RenamesFromDataName + " and " + data.RenamesToDataName, context); } }
public void OnCodeElement(CodeElement e, ParserRuleContext c) { var statement = e as InspectConvertingStatement; if (statement == null) { return; //not our job } var context = c as CodeElementsParser.InspectStatementContext; var seen = new Dictionary <InspectStatement.StartCharacterPosition, bool>(); foreach (var value in Enum.GetValues(typeof(InspectTallyingStatement.StartCharacterPosition))) { seen[(InspectTallyingStatement.StartCharacterPosition)value] = false; } for (int i = 0; i < statement.ReplacingConditions.Length; i++) { var position = statement.ReplacingConditions[i].StartCharacterPosition; if (seen[position.Value]) { string error = "INSPECT: Maximum one " + position.Token.SourceText + " phrase for any one ALL, LEADING, CHARACTERS, FIRST or CONVERTING phrase"; DiagnosticUtils.AddError(statement, error, context.convertingPhrase().countingOrReplacingCondition()[i]); } seen[position.Value] = true; } }
public void OnNode([NotNull] Node node, ParserRuleContext context, CodeModel.Program program) { var header = node.CodeElement as FunctionDeclarationHeader; if (header == null) { return; //not my job } var filesection = node.Get <FileSection>("file"); if (filesection != null) // TCRFUN_DECLARATION_NO_FILE_SECTION { DiagnosticUtils.AddError(filesection.CodeElement, "Illegal FILE SECTION in function \"" + header.Name + "\" declaration", context); } CheckNoGlobalOrExternal(node.Get <DataDivision>("data-division")); CheckParameters(header.Profile, header, context, node); CheckNoLinkageItemIsAParameter(node.Get <LinkageSection>("linkage"), header.Profile); CheckNoPerform(node.SymbolTable.EnclosingScope, node); var headerNameURI = new URI(header.Name); var functions = node.SymbolTable.GetFunction(headerNameURI, header.Profile); if (functions.Count > 1) { DiagnosticUtils.AddError(header, "A function \"" + headerNameURI.Head + "\" with the same profile already exists in namespace \"" + headerNameURI.Tail + "\".", context); } // foreach(var function in functions) { // if (!function.IsProcedure && !function.IsFunction) // DiagnosticUtils.AddError(header, "\""+header.Name.Head+"\" is neither procedure nor function.", context); // } }
public void OnCodeElement(CodeElement e, ParserRuleContext c) { var data = e as DataDescriptionEntry; if (data == null) { return; //not our job } var context = c as CodeElementsParser.DataDescriptionEntryContext; var external = GetContext(data, context.externalClause()); var global = GetContext(data, context.globalClause()); if (data.DataName == null) { if (!data.IsFiller) { DiagnosticUtils.AddError(data, "Data name or FILLER expected", context.dataNameDefinition()); } if (data.IsExternal) { DiagnosticUtils.AddError(data, "Data name must be specified for any entry containing the EXTERNAL clause", external); } if (data.IsGlobal) { DiagnosticUtils.AddError(data, "Data name must be specified for any entry containing the GLOBAL clause", global); } } else { if (data.IsExternal && data.LevelNumber.Value != 01) { DiagnosticUtils.AddError(data, "External is only allowed for level 01", external); } } }
public void OnCodeElement(CodeElement e, ParserRuleContext c) { var statement = e as MoveSimpleStatement; if (statement == null) { return; //not our job } var moveStatementContext = c as CodeElementsParser.MoveStatementContext; if (moveStatementContext != null) { var moveSimpleContext = moveStatementContext.moveSimple(); if (moveSimpleContext != null) { if (statement.StorageAreaWrites != null) { for (int i = 0; i < statement.StorageAreaWrites.Count; i++) { var receiver = statement.StorageAreaWrites[i].StorageArea; if (receiver is FunctionCallResult) { DiagnosticUtils.AddError(statement, "MOVE: illegal <function call> after TO", moveSimpleContext.storageArea1()[i]); } } } } } }
private static void CheckParameter([NotNull] ParameterDescriptionEntry parameter, Node node) { // TCRFUN_LEVEL_88_PARAMETERS if (parameter.LevelNumber?.Value != 1) { DiagnosticUtils.AddError(node, "Condition parameter \"" + parameter.Name + "\" must be subordinate to another parameter."); } if (parameter.DataConditions != null) { foreach (var condition in parameter.DataConditions) { if (condition.LevelNumber?.Value != 88) { DiagnosticUtils.AddError(node, "Condition parameter \"" + condition.Name + "\" must be level 88."); } if (condition.LevelNumber?.Value == 88 && parameter.DataType == DataType.Boolean) { DiagnosticUtils.AddError(node, "The Level 88 symbol '" + parameter.Name + "' cannot be declared under a BOOL typed symbol"); } } } if (parameter.Picture != null) { CrossCompleteChecker.CheckPicture(node, parameter); } var type = parameter.DataType; TypeDefinition foundedType; TypeDefinitionHelper.Check(node, type, out foundedType); //Check if the type exists and is not ambiguous }
private void CheckVariable(Node node, StorageArea storageArea) { if (!storageArea.NeedDeclaration) { return; } var area = storageArea.GetStorageAreaThatNeedDeclaration; if (area.SymbolReference == null) { return; } //Do not handle TCFunctionName, it'll be done by TypeCobolChecker if (area.SymbolReference.IsOrCanBeOfType(SymbolType.TCFunctionName)) { return; } var found = node.SymbolTable.GetVariable(area); if (found.Count < 1) { if (node.SymbolTable.GetFunction(area).Count < 1) { DiagnosticUtils.AddError(node.CodeElement, "Symbol " + area + " is not referenced"); } } if (found.Count > 1) { DiagnosticUtils.AddError(node.CodeElement, "Ambiguous reference to symbol " + area); } }
private void CheckParameter([NotNull] ParameterDescriptionEntry parameter, CodeElement ce, ParserRuleContext context, Node node) { // TCRFUN_LEVEL_88_PARAMETERS if (parameter.LevelNumber.Value != 1) { DiagnosticUtils.AddError(ce, "Condition parameter \"" + parameter.Name + "\" must be subordinate to another parameter.", context); } if (parameter.DataConditions != null) { foreach (var condition in parameter.DataConditions) { if (condition.LevelNumber.Value != 88) { DiagnosticUtils.AddError(ce, "Condition parameter \"" + condition.Name + "\" must be level 88."); } } } if (parameter.Picture != null) { Cobol85CompleteASTChecker.CheckPicture(parameter); } var type = parameter.DataType; TypeDefinitionHelper.Check(node, type); //Check if the type exists and is not ambiguous }
public static void OnNode(Node node) { var functionDeclaration = node as FunctionDeclaration; if (functionDeclaration == null) { return; //not my job } var header = node.CodeElement as FunctionDeclarationHeader; if (header == null) { return; //not my job } CheckParameters(header.Profile, node); CheckNoPerform(node.SymbolTable.EnclosingScope, node); var headerNameURI = new URI(header.Name); var functions = node.SymbolTable.GetFunction(headerNameURI, functionDeclaration.Profile); if (functions.Count > 1) { DiagnosticUtils.AddError(node, "A function \"" + headerNameURI.Head + "\" with the same profile already exists in namespace \"" + headerNameURI.Tail + "\"."); } }
private void CheckTypedef(DataTypeDescriptionEntry typedef, CodeElementsParser.DataDescriptionEntryContext context) { if (typedef == null) { return; } if (typedef.LevelNumber?.Value != 1) { string message = "TYPEDEF clause can only be specified for level 01 entries"; DiagnosticUtils.AddError(typedef, message, context.cobol2002TypedefClause()); } if (typedef.IsExternal) { string message = "EXTERNAL clause cannot be specified with TYPEDEF clause"; foreach (var external in context.externalClause()) { DiagnosticUtils.AddError(typedef, message, external); } } #if EUROINFO_LEGACY_TYPEDEF if (typedef.RestrictionLevel != RestrictionLevel.STRICT) { string message = "Custom EI rule : Only TYPEDEF STRICT is allowed."; DiagnosticUtils.AddError(typedef, message, context.cobol2002TypedefClause()); return; } #endif if (typedef.RestrictionLevel == RestrictionLevel.STRICT) //Manage as a STRICT TYPEDEF { if (typedef.IsSynchronized != null && typedef.IsSynchronized.Value == true) { DiagnosticUtils.AddError(typedef, "SYNC clause cannot be used with a STRICT type definition", context.cobol2002TypedefClause()); } } if (typedef.RestrictionLevel == RestrictionLevel.STRONG) //Manage as a STRONG TYPEDEF { if (typedef.InitialValue != null) { string message = "STRONG TYPEDEF cannot contain VALUE clause:"; foreach (var valeuClause in context.valueClause()) { DiagnosticUtils.AddError(typedef, message, valeuClause); } } if (typedef.Picture != null) { string message = "Elementary TYPEDEF cannot be STRONG"; string rulestack = RuleStackBuilder.GetRuleStack(context.cobol2002TypedefClause()); DiagnosticUtils.AddError(typedef, message, ParseTreeUtils.GetFirstToken(context.cobol2002TypedefClause().STRONG()), rulestack); } } }
private static void Check(SymbolReference renames, Node node) { var founds = node.SymbolTable.GetVariables(renames); if (founds.Count() > 1) { string message = "Illegal RENAMES: Ambiguous reference to symbol \'" + renames + "\'"; DiagnosticUtils.AddError(node, message, MessageCode.SemanticTCErrorInParser); return; } if (!founds.Any()) { string message = "Illegal RENAMES: Symbol \'" + renames + "\' is not referenced"; DiagnosticUtils.AddError(node, message, MessageCode.SemanticTCErrorInParser); return; } var found = founds.First(); var foundCodeElement = found.CodeElement as DataDefinitionEntry; if (found.IsStronglyTyped || found.IsStrictlyTyped) { string message = string.Format("Illegal RENAMES: '{0}' is {1}", renames, found.IsStronglyTyped ? "strongly-typed" : "strictly-typed"); DiagnosticUtils.AddError(node, message, MessageCode.SemanticTCErrorInParser); } if (foundCodeElement?.LevelNumber != null && foundCodeElement.LevelNumber.Value == 01) { string message = string.Format("Illegal RENAMES: '{0}' is level 01", renames); DiagnosticUtils.AddError(node, message, MessageCode.SemanticTCErrorInParser); } }
public static void OnNode(Node node) { var redefinesNode = node as DataRedefines; if (redefinesNode == null) { return; //not my job } var redefinesSymbolReference = redefinesNode.CodeElement().RedefinesDataName; var redefinedVariable = node.SymbolTable.GetRedefinedVariable(redefinesNode, redefinesSymbolReference); if (redefinedVariable == null) { string message = "Illegal REDEFINES: Symbol \'" + redefinesSymbolReference + "\' is not referenced"; DiagnosticUtils.AddError(node, message, MessageCode.SemanticTCErrorInParser); return; } if (redefinedVariable.IsStronglyTyped || redefinedVariable.IsStrictlyTyped) { string message = string.Format("Illegal REDEFINES: '{0}' is {1}", redefinesSymbolReference, redefinedVariable.IsStronglyTyped ? "strongly-typed" : "strictly-typed"); DiagnosticUtils.AddError(node, message, MessageCode.SemanticTCErrorInParser); } }
private static void CheckParameters([NotNull] ParametersProfile profile, Node node) { var parameters = profile.Parameters; foreach (var parameter in profile.InputParameters) { CheckParameter(parameter, node); } foreach (var parameter in profile.InoutParameters) { CheckParameter(parameter, node); } foreach (var parameter in profile.OutputParameters) { CheckParameter(parameter, node); } if (profile.ReturningParameter != null) { CheckParameter(profile.ReturningParameter, node); parameters.Add(profile.ReturningParameter); } foreach ( var duplicatedParameter in parameters.GroupBy(p => p.Name).Where(g => g.Skip(1).Any()).SelectMany(g => g)) //Group on parameter.Name //where group contains more than one item //reexpand to get all duplicated parameters { DiagnosticUtils.AddError(node, string.Format("Parameter with name '{0}' declared multiple times", duplicatedParameter.Name), duplicatedParameter); } }
protected static void Check <T>(T node, [NotNull] IList <T> found) where T : Node { if (found.Count > 1) { DiagnosticUtils.AddError(node.CodeElement, "Symbol \'" + node.Name + "\' already declared"); } }
public override bool Visit(DataDefinition dataDefinition) { if (dataDefinition.CodeElement is CommonDataDescriptionAndDataRedefines) { CheckPicture(dataDefinition); } //Check if DataDefinition is level 88 and declared under BOOL variable if (!(dataDefinition.CodeElement is DataDefinitionEntry)) { return(true); } var levelNumber = ((DataDefinitionEntry)dataDefinition.CodeElement).LevelNumber; var dataDefinitionParent = (dataDefinition.Parent as DataDefinition); if (levelNumber != null && dataDefinitionParent != null && dataDefinitionParent.DataType == DataType.Boolean && levelNumber.Value == 88) { DiagnosticUtils.AddError(dataDefinition.CodeElement, "The Level 88 symbol '" + dataDefinition.Name + "' cannot be declared under a BOOL typed symbol"); } if (levelNumber != null && !(levelNumber.Value == 01 || levelNumber.Value == 77) && dataDefinitionParent == null) { DiagnosticUtils.AddError(dataDefinition.CodeElement, "The variable '" + dataDefinition.Name + "' can only be of level 01 or 77"); } return(true); }
public virtual void StartFunctionProcedureDivision(ProcedureDivisionHeader header) { if (header.UsingParameters != null && header.UsingParameters.Count > 0) { DiagnosticUtils.AddError(header, "TCRFUN_DECLARATION_NO_USING");//TODO#249 } Enter(new ProcedureDivision(header), header); }
public static void CheckRedefines(DataRedefinesEntry redefines, CodeElementsParser.DataDescriptionEntryContext context) { if (context.cobol2002TypedefClause() != null) { string message = "REDEFINES clause cannot be specified with TYPEDEF clause"; DiagnosticUtils.AddError(redefines, message, context.redefinesClause()); } }
public static void OnCodeElement(SetStatementForIndexes set, CodeElementsParser.SetStatementForIndexesContext context) { if (set.SendingVariable == null) { DiagnosticUtils.AddError(set, "Set xxx up/down by xxx: Sending field missing or type unknown", context?.variableOrExpression2()); } }
private static void Check(CodeElement e, SymbolTable table, [NotNull] FunctionCall call, [NotNull] FunctionDeclaration definition) { var parameters = definition.Profile.Parameters; var callArgsCount = call.Arguments != null ? call.Arguments.Length : 0; if (callArgsCount > parameters.Count) { var m = string.Format("Function '{0}' only takes {1} parameter(s)", call.FunctionName, parameters.Count); DiagnosticUtils.AddError(e, m); } for (int c = 0; c < parameters.Count; c++) { var expected = parameters[c]; if (c < callArgsCount) { var actual = call.Arguments[c].StorageAreaOrValue; if (actual.IsLiteral) { continue; } var callArgName = actual.MainSymbolReference != null ? actual.MainSymbolReference.Name : null; var found = table.GetVariable(actual); if (found.Count < 1) { DiagnosticUtils.AddError(e, "Parameter " + callArgName + " is not referenced"); } if (found.Count > 1) { DiagnosticUtils.AddError(e, "Ambiguous reference to parameter " + callArgName); } if (found.Count != 1) { continue; } var type = found[0]; // type check. please note: // 1- if only one of [actual|expected] types is null, overriden DataType.!= operator will detect it // 2- if both are null, we WANT it to break: in TypeCobol EVERYTHING should be typed, // and things we cannot know their type as typed as DataType.Unknown (which is a non-null valid type). if (type != null && (type.DataType != expected.DataType || type.Length > expected.Length)) { var m = string.Format( "Function '{0}' expected parameter '{1}' of type {2} and length {3} and received '{4}' of type {5} and length {6}", call.FunctionName, expected.Name, expected.DataType, expected.Length, callArgName ?? string.Format("position {0}", c + 1), type.DataType, type.Length); DiagnosticUtils.AddError(e, m); } } else { var m = string.Format("Function '{0}' is missing parameter '{1}' of type {2} and length {3}", call.FunctionName, expected.Name, expected.DataType, expected.Length); DiagnosticUtils.AddError(e, m); } } }
public override bool Visit(If ifNode) { if (ifNode?.Children != null && !(ifNode.Children.Last() is End)) { DiagnosticUtils.AddError(ifNode.CodeElement, "\"end-if\" is missing", MessageCode.Warning); } return(true); }
public override bool Visit(Evaluate evaluate) { if (evaluate.GetChildren <WhenOther>().Count == 0) { DiagnosticUtils.AddError(evaluate.CodeElement, "\"when other\" is missing", MessageCode.Warning); } return(true); }
public static void CheckLibrary([NotNull] ProcedureDivision procedureDivision) { //A procedure or a function cannot contains another procedure or function declaration //So we only need to check ProcedureDivision of Program if (!(procedureDivision.Parent is Program)) { return; } //If the procedure division contains a PUBLIC procedure or function then it's considered as a "Library" bool isLibrary = procedureDivision.Children.Any(c => { var f = c.CodeElement as FunctionDeclarationHeader; return(f != null && f.Visibility == AccessModifier.Public); }); if (isLibrary) { bool firstParagraphChecked = false; foreach (var child in procedureDivision.Children) { //TCRFUN_ONLY_PARAGRAPH_AND_PUBLIC_FUNC_IN_LIBRARY if (child is Paragraph) { if (!firstParagraphChecked && !child.Name.Equals("INIT-LIBRARY", StringComparison.InvariantCultureIgnoreCase)) { DiagnosticUtils.AddError(child.CodeElement == null ? procedureDivision : child, "First paragraph of a program which contains public procedure must be INIT-LIBRARY. Move paragraph " + child.Name + " lower in the source."); } firstParagraphChecked = true; continue; //A paragraph is always accepted as a child of ProcedureDivision } //TCRFUN_ONLY_PARAGRAPH_AND_PUBLIC_FUNC_IN_LIBRARY if (!(child is FunctionDeclaration || child is Declaratives)) { DiagnosticUtils.AddError(child.CodeElement == null ? (child is Sentence ? (child.Children.FirstOrDefault(c => c.CodeElement != null) ?? procedureDivision) : procedureDivision) : child, "Inside a library only function declaration or declaratives are allowed " + child.Name + " / " + child.ID); } } var pdiv = procedureDivision.CodeElement as ProcedureDivisionHeader; //TCRFUN_LIBRARY_PROCEDURE_NO_USING if (pdiv?.UsingParameters != null && pdiv.UsingParameters.Count > 0) { DiagnosticUtils.AddError(procedureDivision, "Illegal " + pdiv.UsingParameters.Count + " USING in library PROCEDURE DIVISION."); } } }
public static void CheckStatement(Node node) { var statement = node.CodeElement as SetStatementForIndexes; if (statement != null) { // Check receivers (incremented) var receivers = node.StorageAreaWritesDataDefinition.Values.Select(tuple => tuple.Item2); bool containsPointers = false; bool allArePointers = true; foreach (var receiver in receivers) { if (receiver.Usage == DataUsage.Pointer) { containsPointers = true; var levelNumber = ((DataDefinitionEntry)receiver.CodeElement).LevelNumber; if (levelNumber != null && levelNumber.Value > 49) { DiagnosticUtils.AddError(node, "Only pointer declared in level 01 to 49 can be use in instructions SET UP BY and SET DOWN BY."); break; } receiver.SetFlag(Node.Flag.NodeisIncrementedPointer, true); } else { allArePointers = false; } // Do note break here because it can be all indexes wich is correct or a pointer as last receiver wich is not } if (allArePointers) { node.SetFlag(Node.Flag.NodeContainsPointer, true); } // If the receivers contains at least one Pointer, they must all be pointer else if (containsPointers) { DiagnosticUtils.AddError(node, "[Set [pointer1, pointer2 ...] UP|DOWN BY n] only support pointers."); } // Check sender (increment) int outputResult; // not used if (!int.TryParse(statement.SendingVariable.ToString(), out outputResult)) { // Not an integer var variable = node.GetDataDefinitionForQualifiedName(new URI(statement.SendingVariable.ToString())); if (variable == null || variable.DataType.Name != "Numeric") {// Not an Variable or a notNumeric variable if (statement.SendingVariable.ArithmeticExpression == null) { // Not an arithmetic expressions DiagnosticUtils.AddError(node, "Increment only support integer values, numeric variables and arithmetic expressions"); } } } } }
private void TypeReferencer(DataDescription dataEntry, SymbolTable symbolTable) { if (symbolTable == null) { return; } var types = symbolTable.GetType(dataEntry.DataType); if (types.Count != 1) { return; } var type = types.First(); var circularRefInsideChildren = type.Children.Any(c => { var dataChild = c as DataDescription; if (dataChild == null) { return(false); } var childrenType = symbolTable.GetType(dataChild.DataType).FirstOrDefault(); if (childrenType == null) { return(false); } return(dataEntry.GetParentTypeDefinition == childrenType); //Circular reference detected will return true }); if (type == dataEntry.GetParentTypeDefinition || circularRefInsideChildren) { DiagnosticUtils.AddError(dataEntry, "Type circular reference detected", MessageCode.SemanticTCErrorInParser); return; //Do not continue to prevent further work/crash with circular references } if (symbolTable.TypesReferences.ContainsKey(type)) //If datatype already exists, add ref to the list { if (!symbolTable.TypesReferences[type].Contains(dataEntry)) { symbolTable.TypesReferences[type].Add(dataEntry); } } else { symbolTable.TypesReferences.Add(type, new List <DataDefinition> { dataEntry }); } //Also add all the typedChildren to reference list foreach (var dataDescTypeChild in type.Children.Where(c => c is DataDescription)) { TypeReferencer(dataDescTypeChild as DataDescription, symbolTable); } }
public static void OnNode(Program node) { node.SetFlag(Node.Flag.MissingEndProgram, !(node.Children.LastOrDefault() is End)); if (node.IsFlagSet(Node.Flag.MissingEndProgram)) { DiagnosticUtils.AddError(node, "\"END PROGRAM\" is missing.", MessageCode.Warning); } }
public static void OnCodeElement(DataConditionEntry data, CodeElementsParser.DataConditionEntryContext context) { if (data.LevelNumber?.Value != 88) { DiagnosticUtils.AddError(data, "Data conditions must be level 88", context?.levelNumber); } if (data.DataName == null) { DiagnosticUtils.AddError(data, "Data name must be specified for level-88 items", context?.levelNumber); } }