public virtual void StartCobolProgram(ProgramIdentification programIdentification, LibraryCopyCodeElement libraryCopy) { if (Program == null) { if (SyntaxTree.Root.MainProgram == null) { SyntaxTree.Root.MainProgram = new SourceProgram(TableOfGlobals, programIdentification); Program = SyntaxTree.Root.MainProgram; } else { Program = new StackedProgram(TableOfGlobals, programIdentification); } programsStack = new Stack <Program>(); CurrentProgram = Program; Enter(CurrentProgram, programIdentification, CurrentProgram.SymbolTable); } else { var enclosing = CurrentProgram; CurrentProgram = new NestedProgram(enclosing, programIdentification); Enter(CurrentProgram, programIdentification, CurrentProgram.SymbolTable); } if (libraryCopy != null) { // TCRFUN_LIBRARY_COPY var cnode = new LibraryCopy(libraryCopy); Enter(cnode, libraryCopy, CurrentProgram.SymbolTable); Exit(); } TableOfNamespaces.AddProgram(CurrentProgram); //Add Program to Namespace table. }
/// <summary> /// LoadCopies method. /// </summary> /// <param name="writer">AbstractErrorWriter</param> /// <param name="paths">List<string></param> /// <param name="copyDocumentFormat">DocumentFormat</param> /// <returns>SymbolTable</returns> private static SymbolTable LoadDependencies(AbstractErrorWriter writer, List <string> paths, DocumentFormat format, SymbolTable intrinsicTable) { var parser = new Parser(intrinsicTable); var table = new SymbolTable(intrinsicTable, SymbolTable.Scope.Namespace); //Generate a table of NameSPace containing the dependencies programs based on the previously created intrinsic table. var dependencies = new List <string>(); foreach (var path in paths) { dependencies.AddRange(Tools.FileSystem.GetFiles(path, parser.Extensions, true)); //Get File by name or search the directory for all files } foreach (string path in dependencies) { try { parser.Init(path, new TypeCobolOptions { ExecToStep = ExecutionStep.SemanticCheck }, format); parser.Parse(path); //Parse the dependencie file foreach (var diagnostic in parser.Results.AllDiagnostics()) { Server.AddError(writer, MessageCode.DependenciesLoading, diagnostic.ColumnStart, diagnostic.ColumnEnd, diagnostic.Line, "Error during parsing of " + path + ": " + diagnostic, path); } if (parser.Results.ProgramClassDocumentSnapshot.Program == null) { Server.AddError(writer, MessageCode.DependenciesLoading, "Error: Your dependency file is not included into a program.", path); continue; } table.AddProgram(parser.Results.ProgramClassDocumentSnapshot.Program); //Add program to Namespace symbol table } catch (Exception e) { Server.AddError(writer, MessageCode.DependenciesLoading, e.Message + "\n" + e.StackTrace, path); } } return(table); }
public static SymbolTable LoadDependencies(List <string> paths, DocumentFormat format, SymbolTable intrinsicTable, List <string> inputFiles, EventHandler <DiagnosticsErrorEvent> diagEvent) { var parser = new Parser(intrinsicTable); var diagnostics = new List <Diagnostic>(); var table = new SymbolTable(intrinsicTable, SymbolTable.Scope.Namespace); //Generate a table of NameSPace containing the dependencies programs based on the previously created intrinsic table. var dependencies = new List <string>(); string[] extensions = { ".tcbl", ".cbl", ".cpy" }; foreach (var path in paths) { dependencies.AddRange(Tools.FileSystem.GetFiles(path, extensions, true)); //Get File by name or search the directory for all files } #if EUROINFO_RULES //Create list of inputFileName according to our naming convention in the case of an usage with RDZ var inputFileNames = new List <string>(); foreach (var inputFile in inputFiles) { var inputFileName = Path.GetFileNameWithoutExtension(inputFile); if (inputFileName != null) { //our inputFiles contains a temporary file : the first 8 chars are the program name then there are random chars and then .cbl extension if (inputFileName.Length > 8) { inputFileName = inputFileName.Substring(0, 8); } inputFileNames.Add(inputFileName); } } #endif foreach (string path in dependencies) { #if EUROINFO_RULES //Issue #583, ignore a dependency if the same file will be parsed as an input file just after //Our dependency folder contains file named with 8 chars + tcbl extension string depFileName = Path.GetFileNameWithoutExtension(path); if (depFileName != null && inputFileNames.Any(inputFileName => depFileName.Equals(inputFileName, StringComparison.InvariantCultureIgnoreCase))) { continue; } #endif try { parser.Init(path, new TypeCobolOptions { ExecToStep = ExecutionStep.SemanticCheck }, format); parser.Parse(path); //Parse the dependencie file diagnostics.AddRange(parser.Results.AllDiagnostics()); if (diagEvent != null && diagnostics.Count > 0) { diagnostics.ForEach(d => diagEvent(null, new DiagnosticsErrorEvent() { Path = path, Diagnostic = d })); } if (parser.Results.ProgramClassDocumentSnapshot.Root.Programs == null || parser.Results.ProgramClassDocumentSnapshot.Root.Programs.Count() == 0) { throw new DepedenciesLoadingException("Your dependency file is not included into a program", path, null, logged: true, needMail: false); } foreach (var program in parser.Results.ProgramClassDocumentSnapshot.Root.Programs) { table.AddProgram(program); //Add program to Namespace symbol table } } catch (DepedenciesLoadingException depLoadingEx) { throw depLoadingEx; } catch (Exception e) { throw new DepedenciesLoadingException(e.Message + "\n" + e.StackTrace, path, e); } } return(table); }
private static ReturnCode runOnce2(TypeCobolConfiguration config, AbstractErrorWriter errorWriter) { SymbolTable baseTable = null; #region Dependencies parsing var depParser = new Parser(); bool diagDetected = false; if (config.ExecToStep > ExecutionStep.Preprocessor) { #region Event Diags Handler EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DiagnosticsErrorEvent = delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics diagDetected = true; var diagnostic = diagEvent.Diagnostic; Server.AddError(errorWriter, MessageCode.IntrinsicLoading, diagnostic.ColumnStart, diagnostic.ColumnEnd, diagnostic.Line, "Error while parsing " + diagEvent.Path + ": " + diagnostic, diagEvent.Path); }; EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DependencyErrorEvent = delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics Server.AddError(errorWriter, diagEvent.Path, diagEvent.Diagnostic); }; #endregion depParser.CustomSymbols = Tools.APIHelpers.Helpers.LoadIntrinsic(config.Copies, config.Format, DiagnosticsErrorEvent); //Load intrinsic depParser.CustomSymbols = Tools.APIHelpers.Helpers.LoadDependencies(config.Dependencies, config.Format, depParser.CustomSymbols, config.InputFiles, config.CopyFolders, DependencyErrorEvent); //Load dependencies if (diagDetected) { throw new CopyLoadingException("Diagnostics detected while parsing Intrinsic file", null, null, logged: false, needMail: false); } } baseTable = depParser.CustomSymbols; #endregion var typeCobolOptions = new TypeCobolOptions(config); #if EUROINFO_RULES typeCobolOptions.AutoRemarksEnable = config.AutoRemarks; #endif ReturnCode returnCode = ReturnCode.Success; List <Parser> parsers = new List <Parser>(); List <Compiler.Report.AbstractReport> reports = new List <AbstractReport>(); bool copyAreMissing = false; List <Diagnostic> diagnostics = new List <Diagnostic>(); foreach (var inputFilePath in config.InputFiles) { var parser = new Parser(); parser.CustomSymbols = baseTable; parsers.Add(parser); if (config.ExecToStep > ExecutionStep.SemanticCheck) //If inferior to semantic, use the execstep given by the user. { typeCobolOptions.ExecToStep = ExecutionStep.SemanticCheck; } try { parser.Init(inputFilePath, typeCobolOptions, config.Format, config.CopyFolders); //Init parser create CompilationProject & Compiler before parsing the given file } catch (Exception ex) { throw new ParsingException(MessageCode.ParserInit, ex.Message, inputFilePath, ex); //Make ParsingException trace back to RunOnce() } #region Copy Report Init if (config.ExecToStep >= ExecutionStep.CrossCheck) { if (!string.IsNullOrEmpty(config.ReportCopyMoveInitializeFilePath)) { if (config.UseAntlrProgramParsing) { Compiler.Parser.NodeDispatcher <Antlr4.Runtime.ParserRuleContext> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.CopyMoveInitializeReport <Antlr4.Runtime.ParserRuleContext>(config.ReportCopyMoveInitializeFilePath); reports.Add(report); return(report); }); } else { Compiler.Parser.NodeDispatcher <Compiler.CodeElements.CodeElement> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.CopyMoveInitializeReport <Compiler.CodeElements.CodeElement>(config.ReportCopyMoveInitializeFilePath); reports.Add(report); return(report); }); } } if (!string.IsNullOrEmpty(config.ReportZCallFilePath)) { if (config.UseAntlrProgramParsing) { Compiler.Parser.NodeDispatcher <Antlr4.Runtime.ParserRuleContext> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.ZCallPgmReport <Antlr4.Runtime.ParserRuleContext>(config.ReportZCallFilePath); reports.Add(report); return(report); }); } else { Compiler.Parser.NodeDispatcher <Compiler.CodeElements.CodeElement> .RegisterStaticNodeListenerFactory( () => { var report = new Compiler.Report.ZCallPgmReport <Compiler.CodeElements.CodeElement>(config.ReportZCallFilePath); reports.Add(report); return(report); }); } } } #endregion //Parse input file parser.Parse(inputFilePath); diagnostics.AddRange(parser.Results.AllDiagnostics()); //Get all diags errorWriter.AddErrors(inputFilePath, diagnostics.Take(config.MaximumDiagnostics == 0 ? diagnostics.Count : config.MaximumDiagnostics)); //Write diags into error file if (!string.IsNullOrEmpty(config.HaltOnMissingCopyFilePath)) { if (parser.MissingCopys.Count > 0) { //Collect the missing copies copyAreMissing = true; File.WriteAllLines(config.HaltOnMissingCopyFilePath, parser.MissingCopys); } else { //Delete the file File.Delete(config.HaltOnMissingCopyFilePath); } } if (config.ExecToStep >= ExecutionStep.Preprocessor && !string.IsNullOrEmpty(config.ExtractedCopiesFilePath)) { if (parser.Results.CopyTextNamesVariations.Count > 0) { #if EUROINFO_RULES IEnumerable <string> copiesName; if (config.UseEuroInformationLegacyReplacingSyntax) { copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextName).Distinct(); //Get copies without suffix } else { copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextNameWithSuffix).Distinct(); //Get copies with suffix } #else var copiesName = parser.Results.CopyTextNamesVariations.Select(cp => cp.TextNameWithSuffix).Distinct(); //Get copies with suffix #endif //Create an output document of all the copy encountered by the parser File.WriteAllLines(config.ExtractedCopiesFilePath, copiesName); } else { File.Delete(config.ExtractedCopiesFilePath); } } if (copyAreMissing) { throw new MissingCopyException("Some copy are missing", inputFilePath, null, logged: false, needMail: false); } if (parser.Results.CodeElementsDocumentSnapshot == null && config.ExecToStep > ExecutionStep.Preprocessor) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + inputFilePath + "\" has syntactic error(s) preventing codegen (CodeElements).", inputFilePath); //Make ParsingException trace back to RunOnce() } else if (parser.Results.TemporaryProgramClassDocumentSnapshot == null && config.ExecToStep > ExecutionStep.SyntaxCheck) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + inputFilePath + "\" has semantic error(s) preventing codegen (ProgramClass).", inputFilePath); //Make ParsingException trace back to RunOnce() } if (config.ExecToStep >= ExecutionStep.SemanticCheck) { foreach (var program in parser.Results.TemporaryProgramClassDocumentSnapshot.Root.Programs) { var previousPrograms = baseTable.GetPrograms(); foreach (var previousProgram in previousPrograms) { previousProgram.SymbolTable.GetTableFromScope(SymbolTable.Scope.Namespace).AddProgram(program); } baseTable.AddProgram(program); //Add program to Namespace symbol table } } if (config.ExecToStep >= ExecutionStep.Preprocessor && !string.IsNullOrEmpty(config.ExpandingCopyFilePath)) { try { StringBuilder generatedCobolStringBuilder = new StringBuilder(); var generator = GeneratorFactoryManager.Instance.Create(TypeCobol.Tools.Options_Config.OutputFormat.ExpandingCopy.ToString(), parser.Results, generatedCobolStringBuilder, null, null); var streamWriter = new StreamWriter(config.ExpandingCopyFilePath); generator.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); streamWriter.Write(generatedCobolStringBuilder); streamWriter.Flush(); streamWriter.Close(); } catch (Exception e) { throw new GenerationException(e.Message, inputFilePath, e); } } } //Then do the CrossCheck when all the programs are loaded in SymbolTable if (config.ExecToStep > ExecutionStep.SemanticCheck) { int fileIndex = 0; foreach (var parser in parsers) { parser.Results.RefreshProgramClassDocumentSnapshot(); //Do Cross Check phase for each file diagnostics.Clear(); diagnostics.AddRange(parser.Results.AllDiagnostics()); //Get all diags errorWriter.Errors.Clear(); //Clear errorWriter because of the potential previous diags errorWriter.AddErrors(config.InputFiles[fileIndex], diagnostics.Take(config.MaximumDiagnostics == 0 ? diagnostics.Count : config.MaximumDiagnostics)); //Write diags into error file if (diagnostics.Count > 0) { foreach (var diag in diagnostics) { if (diag.CatchedException != null) { AnalyticsWrapper.Telemetry.TrackException(diag.CatchedException, config.InputFiles[fileIndex]); AnalyticsWrapper.Telemetry.SendMail(diag.CatchedException, config.InputFiles, config.CopyFolders, config.CommandLine); } } } if (diagnostics.Count == 0) { if (config.ExecToStep >= ExecutionStep.CrossCheck && reports != null && reports.Count > 0) { foreach (var report in reports) { try { report.Report(); string msg = string.Format( "Succeed to emit report '{0}'", report.Filepath); Console.WriteLine(msg); } catch (Exception e) { Console.Error.WriteLine(e.Message); throw new GenerationException(e.Message, report.Filepath, e); } } } } if (diagnostics.Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Error)) { throw new PresenceOfDiagnostics("Diagnostics Detected", config.InputFiles[fileIndex]); //Make ParsingException trace back to RunOnce() } if (diagnostics.Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Warning)) { returnCode = ReturnCode.Warning; } if (config.ExecToStep >= ExecutionStep.Generate) { try { //Load skeletons if necessary List <Skeleton> skeletons = null; if (!(string.IsNullOrEmpty(config.skeletonPath))) { skeletons = TypeCobol.Codegen.Config.Config.Parse(config.skeletonPath); } var sb = new StringBuilder(); //Get Generator from specified config.OutputFormat var generator = GeneratorFactoryManager.Instance.Create(config.OutputFormat.ToString(), parser.Results, sb, skeletons, AnalyticsWrapper.Telemetry.TypeCobolVersion); if (generator == null) { throw new GenerationException("Unknown OutputFormat=" + config.OutputFormat + "_", config.InputFiles[fileIndex]); } //Generate and check diagnostics generator.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); if (generator.Diagnostics != null) { errorWriter.AddErrors(config.InputFiles[fileIndex], generator.Diagnostics); //Write diags into error file throw new PresenceOfDiagnostics("Diagnostics Detected", config.InputFiles[fileIndex]); //Make ParsingException trace back to RunOnce() } var outputDirectory = new FileInfo(config.OutputFiles[fileIndex]).Directory; var lockFilePath = outputDirectory.FullName + Path.DirectorySeparatorChar + "~.lock"; if (File.Exists(lockFilePath)) { errorWriter.AddErrors(config.InputFiles[fileIndex], new Diagnostic(MessageCode.GenerationFailled, 0, 0, 0)); } else { var lockWriter = new StreamWriter(lockFilePath); lockWriter.Flush(); lockWriter.Close(); using (var streamWriter = new StreamWriter(config.OutputFiles[fileIndex])) { try { streamWriter.Write(sb); //Write generated Cobol inside file streamWriter.Flush(); } catch (Exception) { throw; } finally { File.Delete(lockFilePath); //Remove lock to allow watchers to read the file streamWriter.Close(); } } } } catch (PresenceOfDiagnostics) { throw; //Throw the same exception to let runOnce() knows there is a problem } catch (GenerationException) { throw; //Throw the same exception to let runOnce() knows there is a problem } catch (Exception e) { //Otherwise create a new GenerationException throw new GenerationException(e.Message, config.InputFiles[fileIndex], e); } fileIndex++; } } } return(returnCode); }
public static SymbolTable LoadDependencies([NotNull] List <string> paths, DocumentFormat format, SymbolTable intrinsicTable, [NotNull] List <string> inputFiles, EventHandler <DiagnosticsErrorEvent> diagEvent) { var parser = new Parser(intrinsicTable); var diagnostics = new List <Diagnostic>(); var table = new SymbolTable(intrinsicTable, SymbolTable.Scope.Namespace); //Generate a table of NameSPace containing the dependencies programs based on the previously created intrinsic table. var dependencies = new List <string>(); string[] extensions = { ".tcbl", ".cbl", ".cpy" }; foreach (var path in paths) { var dependenciesFound = Tools.FileSystem.GetFiles(path, extensions, true); //Issue #668, warn if dependencies path are invalid if (diagEvent != null && dependenciesFound.Count == 0) { diagEvent(null, new DiagnosticsErrorEvent() { Path = path, Diagnostic = new ParserDiagnostic(path + ", no dependencies found", 1, 1, 1, null, MessageCode.DependenciesLoading) }); } dependencies.AddRange(dependenciesFound); //Get File by name or search the directory for all files } #if EUROINFO_RULES //Create list of inputFileName according to our naming convention in the case of an usage with RDZ var programsNames = new List <string>(); foreach (var inputFile in inputFiles) { string PgmName = null; foreach (var line in File.ReadLines(inputFile)) { if (line.StartsWith(" PROGRAM-ID.", StringComparison.InvariantCultureIgnoreCase)) { PgmName = line.Split('.')[1].Trim(); break; } } programsNames.Add(PgmName); } #endif foreach (string path in dependencies) { #if EUROINFO_RULES //Issue #583, ignore a dependency if the same file will be parsed as an input file just after string depFileNameRaw = Path.GetFileNameWithoutExtension(path).Trim(); if (depFileNameRaw != null) { // substring in case of MYPGM.rdz.tcbl var depFileName = depFileNameRaw.Substring(0, depFileNameRaw.IndexOf(".", StringComparison.Ordinal) != -1 ? depFileNameRaw.IndexOf(".", StringComparison.Ordinal) : depFileNameRaw.Length ); if (programsNames.Any(inputFileName => String.Compare(depFileName, inputFileName, StringComparison.OrdinalIgnoreCase) == 0)) { continue; } } #endif try { parser.CustomSymbols = table; //Update SymbolTable parser.Init(path, new TypeCobolOptions { ExecToStep = ExecutionStep.SemanticCheck }, format); parser.Parse(path); //Parse the dependency file diagnostics.AddRange(parser.Results.AllDiagnostics()); if (diagEvent != null && diagnostics.Count > 0) { diagnostics.ForEach(d => diagEvent(null, new DiagnosticsErrorEvent() { Path = path, Diagnostic = d })); } if (parser.Results.TemporaryProgramClassDocumentSnapshot.Root.Programs == null || !parser.Results.TemporaryProgramClassDocumentSnapshot.Root.Programs.Any()) { throw new DepedenciesLoadingException("Your dependency file is not included into a program", path, null, logged: true, needMail: false); } foreach (var program in parser.Results.TemporaryProgramClassDocumentSnapshot.Root.Programs) { var declarationTable = program.SymbolTable.GetTableFromScope(SymbolTable.Scope.Declarations); var globalTable = program.SymbolTable.GetTableFromScope(SymbolTable.Scope.Global); var previousPrograms = table.GetPrograms(); foreach (var previousProgram in previousPrograms) { previousProgram.SymbolTable.GetTableFromScope(SymbolTable.Scope.Namespace).AddProgram(program); } //If there is no public types or functions, then call diagEvent if (diagEvent != null && !globalTable.Types.Values.Any(tds => tds.Any(td => td.CodeElement().Visibility == AccessModifier.Public)) && //No Public Types in Global table !declarationTable.Types.Values.Any(tds => tds.Any(td => td.CodeElement().Visibility == AccessModifier.Public)) && //No Public Types in Declaration table !declarationTable.Functions.Values.Any(fds => fds.Any(fd => fd.CodeElement().Visibility == AccessModifier.Public))) //No Public Functions in Declaration table { diagEvent(null, new DiagnosticsErrorEvent() { Path = path, Diagnostic = new ParserDiagnostic(string.Format("No public types or procedures/functions found in {0}", program.Name), 1, 1, 1, null, MessageCode.Warning) }); continue; } table.AddProgram(program); //Add program to Namespace symbol table } } catch (DepedenciesLoadingException depLoadingEx) { throw depLoadingEx; } catch (Exception e) { throw new DepedenciesLoadingException(e.Message + "\n" + e.StackTrace, path, e); } } //Reset symbolTable of all dependencies return(table); }