cobol-parser 3.3.1__tar.gz → 3.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. cobol_parser-3.4.0/PKG-INFO +765 -0
  2. cobol_parser-3.4.0/README.md +715 -0
  3. cobol_parser-3.4.0/cobol_parser.egg-info/PKG-INFO +765 -0
  4. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobol_parser.egg-info/SOURCES.txt +5 -1
  5. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/__init__.py +1 -1
  6. cobol_parser-3.4.0/cobolparser/analysis/_abend.py +25 -0
  7. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/_sql_whenever.py +9 -0
  8. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/constraints.py +523 -20
  9. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/domains.py +19 -1
  10. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/field_widening.py +93 -11
  11. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/invocation_counts.py +90 -1
  12. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/lint.py +281 -5
  13. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/move_type_checker.py +6 -6
  14. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/analyzer.py +9 -0
  15. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/graph.py +94 -1
  16. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/models.py +5 -0
  17. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/scanner.py +13 -2
  18. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/recursion_risk.py +1 -0
  19. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/redundancy.py +19 -1
  20. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/xref.py +5 -0
  21. cobol_parser-3.4.0/cobolparser/cli/_changed_files.py +242 -0
  22. cobol_parser-3.4.0/cobolparser/cli/_help.py +168 -0
  23. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/cli/parse.py +559 -41
  24. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/config/project.py +3 -3
  25. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/__init__.py +7 -1
  26. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/copybook.py +16 -0
  27. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/dataset.py +48 -2
  28. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/program_layout.py +58 -0
  29. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/program_fixtures.py +47 -2
  30. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/scenarios.py +39 -1
  31. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/verification.py +10 -1
  32. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/lexer.py +78 -6
  33. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/tools.py +5 -1
  34. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/control.py +4 -0
  35. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/data.py +14 -0
  36. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/display_parser.py +170 -1
  37. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/evaluate_parser.py +40 -2
  38. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/scan.py +9 -0
  39. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/pyproject.toml +1 -1
  40. cobol_parser-3.4.0/tests/test_readme_examples.py +156 -0
  41. cobol_parser-3.3.1/PKG-INFO +0 -301
  42. cobol_parser-3.3.1/README.md +0 -251
  43. cobol_parser-3.3.1/cobol_parser.egg-info/PKG-INFO +0 -301
  44. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/LICENSE +0 -0
  45. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/MANIFEST.in +0 -0
  46. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobol_parser.egg-info/dependency_links.txt +0 -0
  47. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobol_parser.egg-info/entry_points.txt +0 -0
  48. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobol_parser.egg-info/requires.txt +0 -0
  49. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobol_parser.egg-info/top_level.txt +0 -0
  50. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/__main__.py +0 -0
  51. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_accel.py +0 -0
  52. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_data_fast.c +0 -0
  53. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_data_fast.pyx +0 -0
  54. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_errors.py +0 -0
  55. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_facts_cache.py +0 -0
  56. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_lexer_fast.c +0 -0
  57. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_lexer_fast.pyx +0 -0
  58. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_lines.py +0 -0
  59. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_literals.py +0 -0
  60. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_preprocess_fast.c +0 -0
  61. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_preprocess_fast.pyx +0 -0
  62. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_source_directive.py +0 -0
  63. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/_storage.py +0 -0
  64. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/__init__.py +0 -0
  65. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/_cics.py +0 -0
  66. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/_files.py +0 -0
  67. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/_names.py +0 -0
  68. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/_procedures.py +0 -0
  69. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/_sql_flow.py +0 -0
  70. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/ast_diff.py +0 -0
  71. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/boundary_inventory.py +0 -0
  72. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/business_rules.py +0 -0
  73. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/call_interface.py +0 -0
  74. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/codebase.py +0 -0
  75. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/complexity.py +0 -0
  76. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/const_fold.py +0 -0
  77. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/crud_matrix.py +0 -0
  78. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/dclgen_check.py +0 -0
  79. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/dead_code.py +0 -0
  80. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/field_lineage.py +0 -0
  81. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/host_var_resolver.py +0 -0
  82. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/ims_segment_analyzer.py +0 -0
  83. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/io_coverage_reporter.py +0 -0
  84. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/io_diagnostics.py +0 -0
  85. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/io_logger.py +0 -0
  86. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/io_sequence.py +0 -0
  87. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/language_env_analyzer.py +0 -0
  88. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/lineage_graph.py +0 -0
  89. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/lineage_jcl.py +0 -0
  90. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/linkage_checker.py +0 -0
  91. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/__init__.py +0 -0
  92. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/condition_text.py +0 -0
  93. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/cycles.py +0 -0
  94. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/edges.py +0 -0
  95. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_flow/statement_text.py +0 -0
  96. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/program_signature.py +0 -0
  97. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/sarif.py +0 -0
  98. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/sql_cics_lint.py +0 -0
  99. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/technical_debt.py +0 -0
  100. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/unused_variables.py +0 -0
  101. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/analysis/value_tracker.py +0 -0
  102. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/batch.py +0 -0
  103. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/cli/__init__.py +0 -0
  104. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/cli/_project_config.py +0 -0
  105. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/cli/coverage.py +0 -0
  106. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/config/__init__.py +0 -0
  107. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/config/_yaml.py +0 -0
  108. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/core/__init__.py +0 -0
  109. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/core/ast_factory.py +0 -0
  110. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/core/exceptions.py +0 -0
  111. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/core/interfaces.py +0 -0
  112. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/core/registry.py +0 -0
  113. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/core/token_stream.py +0 -0
  114. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/definitions/__init__.py +0 -0
  115. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/definitions/_asm.py +0 -0
  116. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/definitions/bms.py +0 -0
  117. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/definitions/csd.py +0 -0
  118. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/definitions/ddl.py +0 -0
  119. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/definitions/ims.py +0 -0
  120. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/dialects/__init__.py +0 -0
  121. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/dialects/ibm_enterprise.py +0 -0
  122. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/dialects/le_signatures.py +0 -0
  123. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/__init__.py +0 -0
  124. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/copybook_data.py +0 -0
  125. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/bundle.py +0 -0
  126. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/compare.py +0 -0
  127. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/decoding.py +0 -0
  128. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/editing.py +0 -0
  129. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/encoding.py +0 -0
  130. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/errors.py +0 -0
  131. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/layout.py +0 -0
  132. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/layout_offsets.py +0 -0
  133. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/options.py +0 -0
  134. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/storage.py +0 -0
  135. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/values.py +0 -0
  136. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/data/views.py +0 -0
  137. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/generators/flowchart.py +0 -0
  138. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/jcl/__init__.py +0 -0
  139. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/jcl/bindings.py +0 -0
  140. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/jcl/models.py +0 -0
  141. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/jcl/parser.py +0 -0
  142. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/jcl/programs.py +0 -0
  143. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/__init__.py +0 -0
  144. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/claims.py +0 -0
  145. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/codebase_index.py +0 -0
  146. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/envelope.py +0 -0
  147. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/facts.py +0 -0
  148. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/hints.py +0 -0
  149. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/jcl_tools.py +0 -0
  150. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/languages.py +0 -0
  151. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/link_decks.py +0 -0
  152. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/navigation.py +0 -0
  153. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/prompts.py +0 -0
  154. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/server.py +0 -0
  155. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/slicing.py +0 -0
  156. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/sort_layout.py +0 -0
  157. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/mcp/workspace.py +0 -0
  158. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/__init__.py +0 -0
  159. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/ast_base.py +0 -0
  160. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/data_items.py +0 -0
  161. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/program.py +0 -0
  162. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/sql_statements.py +0 -0
  163. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/__init__.py +0 -0
  164. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/arithmetic.py +0 -0
  165. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/base.py +0 -0
  166. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/call.py +0 -0
  167. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/communication.py +0 -0
  168. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/io.py +0 -0
  169. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/legacy.py +0 -0
  170. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/misc.py +0 -0
  171. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/models/statements/report_writer.py +0 -0
  172. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parser.py +0 -0
  173. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/__init__.py +0 -0
  174. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/__init__.py +0 -0
  175. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/base.py +0 -0
  176. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/data.py +0 -0
  177. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/data_clauses.py +0 -0
  178. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/data_file_description.py +0 -0
  179. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/data_report_description.py +0 -0
  180. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/data_special_entries.py +0 -0
  181. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/environment.py +0 -0
  182. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/environment_sections.py +0 -0
  183. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/environment_select.py +0 -0
  184. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/factory.py +0 -0
  185. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/identification.py +0 -0
  186. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/procedure.py +0 -0
  187. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/procedure_boundaries.py +0 -0
  188. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/procedure_recovery.py +0 -0
  189. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/divisions/procedure_registry.py +0 -0
  190. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/__init__.py +0 -0
  191. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/_conditions.py +0 -0
  192. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/_utils.py +0 -0
  193. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/accept_parser.py +0 -0
  194. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/allocate_free_parsers.py +0 -0
  195. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/arithmetic_parsers.py +0 -0
  196. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/call_parser.py +0 -0
  197. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/close_parser.py +0 -0
  198. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/communication_parsers.py +0 -0
  199. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/delete_parser.py +0 -0
  200. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/entry_parser.py +0 -0
  201. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/exception_parsers.py +0 -0
  202. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/go_parser.py +0 -0
  203. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/ibm_exec_statements.py +0 -0
  204. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/if_parser.py +0 -0
  205. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/initialize_inspect_parsers.py +0 -0
  206. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/invoke_parser.py +0 -0
  207. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/legacy_verb_parsers.py +0 -0
  208. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/move_parser.py +0 -0
  209. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/open_parser.py +0 -0
  210. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/perform_parser.py +0 -0
  211. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/read_parser.py +0 -0
  212. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/report_writer_parsers.py +0 -0
  213. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/rewrite_parser.py +0 -0
  214. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/search_parser.py +0 -0
  215. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/set_parser.py +0 -0
  216. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/simple_statement_parsers.py +0 -0
  217. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/sort_merge_parsers.py +0 -0
  218. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/start_parser.py +0 -0
  219. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/stop_parser.py +0 -0
  220. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/string_unstring_parsers.py +0 -0
  221. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/unlock_parser.py +0 -0
  222. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/write_parser.py +0 -0
  223. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/parsers/statements/xml_json_parser.py +0 -0
  224. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/plugins/__init__.py +0 -0
  225. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/plugins/core.py +0 -0
  226. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/__init__.py +0 -0
  227. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/_normalize.py +0 -0
  228. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/copy_statement_parser.py +0 -0
  229. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/copybook_expander.py +0 -0
  230. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/models.py +0 -0
  231. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/path_resolver.py +0 -0
  232. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/replace_statement.py +0 -0
  233. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/preprocess/source_format.py +0 -0
  234. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/profiling.py +0 -0
  235. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/cobolparser/py.typed +0 -0
  236. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/setup.cfg +0 -0
  237. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/setup.py +0 -0
  238. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/tests/test_all_samples.py +0 -0
  239. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/tests/test_okf_claims.py +0 -0
  240. {cobol_parser-3.3.1 → cobol_parser-3.4.0}/tests/test_okf_staleness_map.py +0 -0
@@ -0,0 +1,765 @@
1
+ Metadata-Version: 2.4
2
+ Name: cobol-parser
3
+ Version: 3.4.0
4
+ Summary: A comprehensive COBOL parser for Python with IBM Enterprise COBOL focus
5
+ Author-email: Samuel Dion <sam94dion@gmail.com>
6
+ License: AGPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/Landparty/cobol-parser
8
+ Project-URL: Repository, https://github.com/Landparty/cobol-parser
9
+ Project-URL: Bug Tracker, https://github.com/Landparty/cobol-parser/issues
10
+ Keywords: cobol,parser,mainframe,ibm,enterprise,legacy
11
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: Software Development :: Compilers
20
+ Classifier: Topic :: Text Processing :: Linguistic
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Provides-Extra: fast
25
+ Requires-Dist: cython>=3.0; extra == "fast"
26
+ Provides-Extra: jcl
27
+ Requires-Dist: jcl-parser>=2.0.0; extra == "jcl"
28
+ Provides-Extra: pl1
29
+ Requires-Dist: landparty-pl1-parser>=2.0.0; extra == "pl1"
30
+ Provides-Extra: hlasm
31
+ Requires-Dist: hlasm-parser>=0.2.2; extra == "hlasm"
32
+ Provides-Extra: mcp
33
+ Requires-Dist: mcp<2,>=1.10; extra == "mcp"
34
+ Provides-Extra: dev
35
+ Requires-Dist: jcl-parser>=2.0.0; extra == "dev"
36
+ Requires-Dist: mcp<2,>=1.10; extra == "dev"
37
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
38
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
39
+ Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
40
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
41
+ Requires-Dist: black>=23.0.0; extra == "dev"
42
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
43
+ Requires-Dist: cython>=3.0; extra == "dev"
44
+ Provides-Extra: docs
45
+ Requires-Dist: sphinx>=7.0.0; extra == "docs"
46
+ Requires-Dist: sphinx-rtd-theme>=1.3.0; extra == "docs"
47
+ Provides-Extra: profiling
48
+ Requires-Dist: psutil>=5.9; extra == "profiling"
49
+ Dynamic: license-file
50
+
51
+ # cobol-parser
52
+
53
+ A COBOL parser for Python with an IBM Enterprise COBOL focus. It turns COBOL
54
+ source into a traversable AST (JSON export, error recovery, copybook
55
+ expansion with a source map back to the original lines), and builds static
56
+ analyzers, test-data generators, a z/OS JCL front end and an MCP server for AI
57
+ agents on top of it.
58
+
59
+ 458 of the 459 NIST COBOL-85 programs in `examples/cobol/` parse cleanly (the
60
+ one that does not, SM101A, needs its copybooks expanded first).
61
+
62
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://www.python.org/downloads/)
63
+ [![PyPI](https://img.shields.io/pypi/v/cobol-parser.svg)](https://pypi.org/project/cobol-parser/)
64
+ [![Coverage](https://img.shields.io/badge/coverage-90%25%20enforced-green.svg)](.okf/tests.md)
65
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE)
66
+
67
+ ## Contents
68
+
69
+ - [Install](#install)
70
+ - [Quick start](#quick-start)
71
+ - [Every command, with an example](#every-command-with-an-example)
72
+ - [Parse and preprocess](#parse-and-preprocess)
73
+ - [Lint and CI](#lint-and-ci)
74
+ - [Analyze one program](#analyze-one-program)
75
+ - [Analyze a codebase](#analyze-a-codebase)
76
+ - [Test data](#test-data)
77
+ - [Reference and integrations](#reference-and-integrations)
78
+ - [Exit codes](#exit-codes)
79
+ - [The Python API, with examples](#the-python-api-with-examples)
80
+ - [Language coverage](#language-coverage)
81
+ - [Documentation](#documentation)
82
+ - [Development](#development)
83
+
84
+ ## Install
85
+
86
+ ```bash
87
+ pip install cobol-parser # the library and the cobol-parser CLI
88
+ pip install 'cobol-parser[mcp]' # plus the MCP server
89
+ pip install 'cobol-parser[jcl]' # plus JCL (through jcl-parser)
90
+ ```
91
+
92
+ Requires Python 3.11, 3.12 or 3.13. The core library has no runtime
93
+ dependencies. Optional extras:
94
+
95
+ | Extra | Adds |
96
+ |---|---|
97
+ | `mcp` | `cobol-parser mcp`, the MCP server ([docs/mcp-server.md](docs/mcp-server.md)) |
98
+ | `jcl` | `cobol-parser jcl`, and the JCL joins in `field-impact`, `widen-check` and the MCP server |
99
+ | `pl1`, `hlasm` | PL/I and assembler programs in the MCP server's call graph |
100
+ | `fast` | Cython, to build the optional accelerators from source |
101
+ | `dev`, `docs` | the test, lint and docs toolchain for working on this repo |
102
+
103
+ To get the CLI on your `PATH` without a project virtualenv:
104
+
105
+ ```bash
106
+ uv tool install cobol-parser
107
+ uv tool install --editable . # from a clone, picking up code changes
108
+ ```
109
+
110
+ The install is pure Python by default. The PyPI wheels also carry three
111
+ compiled Cython accelerators (about 3x lexer throughput), used only when
112
+ `COBOLPARSER_ACCEL=1` is set at run time. From a clone, the same variable at
113
+ build time compiles them:
114
+
115
+ ```bash
116
+ pip install -e ".[fast]"
117
+ COBOLPARSER_ACCEL=1 python setup.py build_ext --inplace
118
+ export COBOLPARSER_ACCEL=1
119
+ ```
120
+
121
+ ## Quick start
122
+
123
+ ```bash
124
+ cobol-parser parse src/ORDPOST.cbl --copybook-path copybooks -o ordpost.json
125
+ cobol-parser lint src/*.cbl --format text --fail-on error
126
+ cobol-parser --help # every command, grouped by task
127
+ cobol-parser lint --help # every flag of one command, with examples
128
+ ```
129
+
130
+ ```python
131
+ from cobolparser import parse_cobol
132
+
133
+ result = parse_cobol("src/ORDPOST.cbl") # a path, or the source text itself
134
+ if result.success:
135
+ print(result.ast.program_name) # ORDPOST
136
+ for error in result.errors:
137
+ print(error)
138
+ ```
139
+
140
+ ## Every command, with an example
141
+
142
+ `cobol-parser` has <!-- okf:gen cli-subcommand-count -->41<!-- /okf:gen -->
143
+ subcommands, one per analyzer or generator. Every one writes JSON to stdout
144
+ by default (`-o FILE` writes a file, `--compact` drops the indentation), and
145
+ `cobol-parser <command> --help` lists all its flags with more examples. The full flag reference is the generated table in
146
+ [.okf/cli.md](.okf/cli.md#subcommand-reference).
147
+
148
+ The examples below are run from the root of a project laid out like this.
149
+ The `cobol.yml` saves passing `--copybook-path copybooks` and
150
+ `--proc-path proclib` to every command (a flag on the command line always
151
+ wins over it):
152
+
153
+ ```text
154
+ cobol.yml copybook_path: [copybooks], proc_path: [proclib]
155
+ src/ ORDEDIT.cbl ORDVAL.cbl ORDPOST.cbl POSTDOM.cbl POSTINTL.cbl ...
156
+ copybooks/ ORDREC.cpy HISTREC.cpy ADDRREC.cpy ...
157
+ jcl/ ORDNIGHT.jcl ORDMONTH.jcl
158
+ proclib/ ORDEDITP ORDRPTP (cataloged PROCs)
159
+ ```
160
+
161
+ ```yaml
162
+ # cobol.yml
163
+ version: 1
164
+ project:
165
+ copybook_path: [copybooks]
166
+ proc_path: [proclib]
167
+ ```
168
+
169
+ The order programs come from [tests/eval/shop/](tests/eval/shop/), and the
170
+ SQL, CICS, IMS and LE examples use the programs in
171
+ [tests/samples/enterprise/](tests/samples/enterprise/).
172
+ [tests/test_readme_examples.py](tests/test_readme_examples.py) builds this
173
+ project from them and runs every example in this section and the next.
174
+
175
+ Flags most commands share: `--copybook-path DIR` (repeatable),
176
+ `--define SYMBOL[=VALUE]` for `>>DEFINE`, `--source-format auto|fixed|free`,
177
+ `--encoding ENC`, `--program NAME` (pick one unit of a nested program),
178
+ `--error-recovery fail-fast|collect-all` (the CLI defaults to `collect-all`)
179
+ and, on any command, `--config FILE` / `--no-config`.
180
+
181
+ ### Parse and preprocess
182
+
183
+ | Command | What it gives you |
184
+ |---|---|
185
+ | `parse` | The whole program as AST JSON (`--find-type` to keep one node type, `--errors`, `--stats`) |
186
+ | `batch` | Many programs parsed in parallel, one JSON entry per file |
187
+ | `expand` | The source with every `COPY` expanded, and optionally a map back to the original lines |
188
+ | `preprocess` | Fixed-format source turned into free-form text (columns 8-72, continuations merged) |
189
+ | `tokenize` | The lexer's token stream |
190
+
191
+ ```bash
192
+ cobol-parser parse src/ORDPOST.cbl -o ordpost.json
193
+ cobol-parser parse src/ORDPOST.cbl --find-type CallStatement
194
+ cobol-parser batch --glob 'src/*.cbl' --workers 4 -o asts.json
195
+ cobol-parser expand src/ORDPOST.cbl --source-map
196
+ cobol-parser preprocess src/ORDPOST.cbl --define DEBUG
197
+ cobol-parser tokenize src/ORDPOST.cbl
198
+ ```
199
+
200
+ `cobol-parser src/ORDPOST.cbl`, with no command, is `parse`.
201
+
202
+ ### Lint and CI
203
+
204
+ | Command | What it gives you |
205
+ |---|---|
206
+ | `lint` | Every checker in one pass, one severity-graded finding list (`json`, `text`, `sarif`, `github`) |
207
+ | `scan` | Analyzers over a whole source tree, with per-file fault isolation, cross-file duplicate paragraphs and an on-disk cache |
208
+ | `config` | The `cobol.yml` in effect, and where it came from |
209
+
210
+ ```bash
211
+ cobol-parser lint src/ORDPOST.cbl --format text
212
+ cobol-parser lint src/*.cbl --format text --min-severity warning --fail-on error
213
+ cobol-parser lint --glob 'src/**/*.cbl' --rule dead-code --rule move-type-check
214
+ cobol-parser lint --changed-since origin/main --format github --fail-on error
215
+ cobol-parser lint src/*.cbl --format sarif -o lint.sarif
216
+ cobol-parser scan --glob 'src/*.cbl' --analyzer health --clones --cache-dir .cache
217
+ cobol-parser scan src/*.cbl --format sarif -o scan.sarif
218
+ cobol-parser config
219
+ ```
220
+
221
+ ```text
222
+ $ cobol-parser lint src/ORDPOST.cbl --format text
223
+ src/ORDPOST.cbl:54:8: warning [dead-code] paragraph 9000-OLD-RECALC can never be reached
224
+ src/ORDPOST.cbl:56:8: warning [dead-code] paragraph 9100-OLD-AUDIT can never be reached
225
+ 2 finding(s): 0 error, 2 warning, 0 info (10 rule(s) ran)
226
+ ```
227
+
228
+ `lint` runs nine analyzers over one parse: dead code, unused variables, MOVE
229
+ type checks, I/O sequencing, LINKAGE checks, recursion risk, complexity,
230
+ DCLGEN and SQL/CICS checks, plus `line-length` (fixed-format text past
231
+ column 80, or a word cut at column 72, in the program and its copybooks).
232
+ `--rule` narrows the run, `--min-severity` the output, and `--fail-on error`
233
+ exits 3 when a finding at that severity was reported, so it can gate a build.
234
+ It takes many files at once (`FILE...`, `--glob`, `--files-from`),
235
+ `--changed-since REF` lints only the programs a git change touched (and those
236
+ that `COPY` a changed copybook), and `--format github` annotates the pull
237
+ request. `lint`, `scan` and `call-check` write SARIF 2.1.0 with
238
+ `--format sarif`, which GitHub code scanning and IDE problem panes read
239
+ directly. CI recipe and pre-commit hooks: [docs/ci-lint.md](docs/ci-lint.md).
240
+
241
+ `scan` runs `health` and `redundancy` by default; `--analyzer` picks others
242
+ (`dead-code`, `complexity`, `lint`, ...). With `--cache-dir`, a file whose
243
+ source, copybooks and copybook directories are unchanged reuses its report
244
+ from the last run.
245
+
246
+ ### Analyze one program
247
+
248
+ Each command reads one program (or, for `data-items`, a bare copybook) and
249
+ writes one report.
250
+
251
+ | Command | What it gives you |
252
+ |---|---|
253
+ | `dead-code` | Paragraphs and sections no path reaches |
254
+ | `unused-variables` | Data items the PROCEDURE DIVISION never references |
255
+ | `program-flow` | The control-flow graph (PERFORM, GO TO, CALL, fall-through) as JSON, Mermaid or DOT |
256
+ | `recursion-check` | PERFORM and GO TO cycles, recursive CALLs |
257
+ | `complexity` | Cyclomatic complexity per paragraph and section |
258
+ | `health` | A composite technical-debt score with its worst offenders |
259
+ | `redundancy` | Dead code, unused data and duplicated paragraphs together |
260
+ | `io-sequence` | OPEN / READ / WRITE / CLOSE ordering mistakes |
261
+ | `move-type-check` | MOVEs between incompatible categories |
262
+ | `linkage-check` | LINKAGE items against the `USING` of the PROCEDURE DIVISION and ENTRY |
263
+ | `sql-cics-check` | Embedded SQL and CICS pitfalls (unchecked SQLCODE, missing RESP, ...) |
264
+ | `dclgen-check` | SQL host variables against their DCLGEN columns |
265
+ | `analyze` | The targets a dynamic `CALL identifier` can reach |
266
+ | `language-env` | Intrinsic functions and LE callable services the program uses |
267
+ | `ims-dli` | IMS DL/I calls and the segments they reference |
268
+ | `data-items` | Every data item's byte offset, length, USAGE, REDEFINES and level-88 values |
269
+ | `program-signature` | The program's calling interface, with a ready-made `CALL` |
270
+ | `xref` | A cross-reference of every symbol: where it is defined, read and written |
271
+ | `business-rules` | The decisions, validations and calculations, as rules |
272
+ | `lineage` | Where one field's value flows inside the program |
273
+ | `diff` | What changed in behavior between two versions (reformatting is no change) |
274
+
275
+ ```bash
276
+ cobol-parser dead-code src/ORDPOST.cbl
277
+ cobol-parser unused-variables src/ORDPOST.cbl --exclude-copybook-variables
278
+ cobol-parser program-flow src/ORDPOST.cbl --format mermaid -o flow.mmd
279
+ cobol-parser recursion-check src/ORDPOST.cbl
280
+ cobol-parser complexity src/ORDPOST.cbl
281
+ cobol-parser health src/ORDPOST.cbl
282
+ cobol-parser redundancy src/ORDPOST.cbl --min-clone-statements 5
283
+ cobol-parser io-sequence src/ORDPOST.cbl
284
+ cobol-parser move-type-check src/ORDPOST.cbl
285
+ cobol-parser linkage-check src/POSTDOM.cbl
286
+ cobol-parser sql-cics-check src/DB2BATCH.cbl
287
+ cobol-parser dclgen-check src/DB2BATCH.cbl
288
+ cobol-parser analyze src/ORDPOST.cbl
289
+ cobol-parser language-env src/LESERV.cbl
290
+ cobol-parser ims-dli src/IMSMPP.cbl
291
+ cobol-parser data-items copybooks/ORDREC.cpy
292
+ cobol-parser program-signature src/POSTDOM.cbl
293
+ cobol-parser xref src/ORDPOST.cbl
294
+ cobol-parser business-rules src/ORDVAL.cbl --format text
295
+ cobol-parser lineage src/ORDPOST.cbl --field ORD-AMT --format text
296
+ cobol-parser diff old/ORDPOST.cbl src/ORDPOST.cbl --format text
297
+ ```
298
+
299
+ ```text
300
+ $ cobol-parser diff old/ORDPOST.cbl src/ORDPOST.cbl --format text
301
+ PROGRAM ORDPOST -> ORDPOST
302
+ 3 changes
303
+
304
+ data:
305
+ ~ [value-changed] WS-OLD-RATE: WS-OLD-RATE VALUE changed from 0.0150 to 0.0125
306
+
307
+ procedure:
308
+ ~ [condition-changed] 2000-POST: IF condition changed: IF ORD-HELD OR ORD-REJECTED -> IF ORD-HELD
309
+ ~ [paragraph-body-changed] 2000-POST: paragraph 2000-POST body changed
310
+ ...
311
+ ```
312
+
313
+ ### Analyze a codebase
314
+
315
+ | Command | What it gives you |
316
+ |---|---|
317
+ | `codebase-graph` | The CALL / LINK / XCTL and COPY graph of a source tree (JSON, DOT, Mermaid) |
318
+ | `copybook-impact` | Every program a copybook change reaches, through nested `COPY` chains |
319
+ | `call-check` | Every `CALL` against the callee's `USING`: argument count, BY VALUE / BY REFERENCE, byte length, USAGE, `RETURNING` |
320
+ | `field-impact` | Where a field's value flows across programs, files, DB2 columns and JCL datasets |
321
+ | `widen-check` | What breaks if a field's PICTURE changes |
322
+ | `jcl` | Which program each JCL step runs, and each DD's dataset (needs the `[jcl]` extra) |
323
+
324
+ ```bash
325
+ cobol-parser codebase-graph src/ --format mermaid -o graph.mmd
326
+ cobol-parser copybook-impact ORDREC src/
327
+ cobol-parser call-check src/ --format text --fail-on error
328
+ cobol-parser field-impact ORD-AMT src/ --jcl jcl/ --format text
329
+ cobol-parser field-impact --dataset PROD.ORD.HISTORY src/ --jcl jcl/ --format text
330
+ cobol-parser widen-check ORD-CUST-ID src/ --to '9(10)' --jcl jcl/ --format text
331
+ cobol-parser jcl jcl/ORDNIGHT.jcl --bindings
332
+ cobol-parser jcl jcl/ORDNIGHT.jcl --dd-map
333
+ ```
334
+
335
+ ```text
336
+ $ cobol-parser widen-check ORD-CUST-ID src/ --to '9(10)' --jcl jcl/ --format text
337
+ ORD-CUST-ID -> PIC 9(10)
338
+ ORDEDIT:ORD-REC.ORD-CUST-ID PIC 9(8) (8 bytes) -> PIC 9(10) (10 bytes)
339
+ ...
340
+ ERROR truncation ORDPOST:HIST-REC.HIST-CUST-ID (line 48)
341
+ the value reaches a field holding 8 digits; the new PICTURE carries 10 digits: loses high-order digits
342
+ ...
343
+ ```
344
+
345
+ A dynamic `CALL` is followed to every target its variable can hold. When the
346
+ byte length changes, `widen-check` also lists the records whose later fields
347
+ shift, the `REDEFINES` that overlay the field, the files whose LRECL changes
348
+ (and the other programs reading the same dataset), and the CALL / LINKAGE
349
+ records on both sides.
350
+
351
+ ### Test data
352
+
353
+ | Command | What it gives you |
354
+ |---|---|
355
+ | `gen-data` | Synthetic records that fit each field's PICTURE, USAGE and level-88 values, as CSV, JSON, record bytes or hex |
356
+ | `decode` | A record file (ASCII or EBCDIC, fixed or variable) read back through a copybook |
357
+ | `compare` | Two record files compared field by field, matched on a key |
358
+ | `gen-fixtures` | A test bundle for a whole program: one scenario per branch, the data each file, CALL, SQL or CICS boundary supplies, and what to assert |
359
+
360
+ ```bash
361
+ cobol-parser gen-data copybooks/ORDREC.cpy --rows 100 --seed 7 -o orders.csv
362
+ cobol-parser gen-data copybooks/ORDREC.cpy --rows 100 --seed 7 --format record --charset ebcdic -o expected.dat
363
+ cobol-parser gen-data copybooks/ORDREC.cpy --rows 99 --seed 7 --format record --charset ebcdic -o actual.dat
364
+ cobol-parser decode expected.dat --copybook copybooks/ORDREC.cpy --charset ebcdic --max-records 5
365
+ cobol-parser compare expected.dat actual.dat --copybook copybooks/ORDREC.cpy --charset ebcdic --key ORD-ID
366
+ cobol-parser gen-fixtures src/ORDPOST.cbl --list-boundaries
367
+ cobol-parser gen-fixtures src/ORDPOST.cbl --scenarios all --seed 7 -o bundle.json
368
+ cobol-parser gen-fixtures src/ORDPOST.cbl --scenarios branches --format csv-dir -o fixtures/
369
+ ```
370
+
371
+ ```text
372
+ $ cobol-parser compare expected.dat actual.dat --copybook copybooks/ORDREC.cpy --charset ebcdic --key ORD-ID
373
+ compare ORD-REC (view ORD-REC), key ORD-ID, comparing values
374
+ expected: 100 records, actual: 99 records
375
+ matched 99, changed 0, missing 1, extra 0
376
+ ...
377
+ ```
378
+
379
+ A `--seed` makes `gen-data` and `gen-fixtures` output byte-identical across
380
+ runs. `compare` exits like `cmp`: 0 when the files match, 1 when they differ,
381
+ 2 when the run failed. The bundle format is in
382
+ [docs/fixture-bundle-schema.md](docs/fixture-bundle-schema.md).
383
+
384
+ ### Reference and integrations
385
+
386
+ | Command | What it gives you |
387
+ |---|---|
388
+ | `le-info` | The signature of an LE callable service or intrinsic function, from the built-in catalogue |
389
+ | `mcp` | A read-only MCP server that gives AI agents these analyzers (needs the `[mcp]` extra) |
390
+
391
+ ```bash
392
+ cobol-parser le-info CEEDAYS
393
+ cobol-parser le-info NUMVAL-C
394
+ cobol-parser le-info --kind service
395
+ claude mcp add cobol -- cobol-parser mcp --root /path/to/checkout
396
+ ```
397
+
398
+ The MCP server's tools answer "what is this program", "what is this field and
399
+ where is it used", "who calls this", "what does a change to this copybook
400
+ reach" and "show me this paragraph", with a `file:line` for every fact and a
401
+ list of what they could not check. See [docs/mcp-server.md](docs/mcp-server.md).
402
+ The repo also ships a `cobol-analysis` agent skill
403
+ ([.claude/skills/cobol-analysis/SKILL.md](.claude/skills/cobol-analysis/SKILL.md))
404
+ that teaches an agent which subcommand answers which question.
405
+
406
+ ### Exit codes
407
+
408
+ | Code | Meaning |
409
+ |---|---|
410
+ | 0 | Success. Analyzer findings alone never fail a run |
411
+ | 1 | A file could not be read, parsed or written |
412
+ | 2 | The command line was rejected, or some input only partly parsed (the output is still written) |
413
+ | 3 | A gate tripped: `--fail-on` (`lint`, `call-check`, `widen-check`) or `jcl --strict` |
414
+
415
+ `compare` is the exception: 1 means "the files differ".
416
+
417
+ ## The Python API, with examples
418
+
419
+ Everything the CLI does is a library call. Each block below runs on its own
420
+ from the project root shown above.
421
+
422
+ ### Parse
423
+
424
+ ```python
425
+ from cobolparser import CobolParser, ErrorRecoveryMode, parse_cobol
426
+
427
+ result = parse_cobol("src/ORDVAL.cbl") # FAIL_FAST: stops at the first error
428
+ print(result.success, result.errors, result.warnings)
429
+ print(result.ast.program_name) # ORDVAL
430
+ print(len(result.ast.find_all_by_type("CallStatement")))
431
+ json_text = result.ast.to_json()
432
+
433
+ parser = CobolParser(error_recovery=ErrorRecoveryMode.COLLECT_ALL)
434
+ result = parser.parse(" IDENTIFICATION DIVISION.\n PROGRAM-ID. HELLO.\n")
435
+ print(result.ast.program_name) # HELLO
436
+ ```
437
+
438
+ `parse_cobol` takes a path or the source text. `ParseResult` also carries
439
+ `statistics` and, after copybook expansion, `expansion_source_map`.
440
+
441
+ ### Copybooks, preprocessing and tokens
442
+
443
+ ```python
444
+ from pathlib import Path
445
+
446
+ from cobolparser import (
447
+ expand_copybooks,
448
+ normalize_fixed_format,
449
+ parse_cobol_with_expansion,
450
+ tokenize_cobol,
451
+ )
452
+
453
+ source = Path("src/ORDPOST.cbl").read_text()
454
+
455
+ result = parse_cobol_with_expansion(source, "src/ORDPOST.cbl", copybook_paths=["copybooks"])
456
+ print(result.success)
457
+
458
+ expansion = expand_copybooks(source, ["copybooks"])
459
+ print(expansion.included_copybooks) # the copybook files it read
460
+
461
+ free_form = normalize_fixed_format(source) # columns 8-72, comments dropped
462
+ tokens = tokenize_cobol(source)
463
+ print(tokens[0].type.name, tokens[0].value) # IDENTIFICATION_DIVISION IDENTIFICATION
464
+ ```
465
+
466
+ ### Many files
467
+
468
+ ```python
469
+ from glob import glob
470
+
471
+ from cobolparser import ScanOptions, cross_file_clone_groups, parse_files, scan_files
472
+
473
+ for item in parse_files(glob("src/*.cbl"), workers=4):
474
+ print(item.path, item.result.success if item.result else item.read_error)
475
+
476
+ report = scan_files(
477
+ glob("src/*.cbl"),
478
+ ScanOptions(analyzers=("health", "dead-code"), copybook_paths=("copybooks",)),
479
+ )
480
+ print(len(report.ok_files), len(report.failed_files))
481
+ print(cross_file_clone_groups(report))
482
+ ```
483
+
484
+ `cobolparser.batch.parse_files_with_copybooks(paths, copybook_paths=[...])`
485
+ parses many files with their copybooks expanded.
486
+
487
+ ### Analyze one program
488
+
489
+ Every analyzer takes a parsed `CobolProgram` and returns a report with
490
+ `to_dict()`. Most are `<Analyzer>().analyze(ast)`; the checkers are
491
+ `.check(ast)`.
492
+
493
+ ```python
494
+ from cobolparser import (
495
+ BusinessRuleExtractor,
496
+ ComplexityAnalyzer,
497
+ CRUDMatrixGenerator,
498
+ DclgenChecker,
499
+ DeadCodeAnalyzer,
500
+ DynamicCallAnalyzer,
501
+ IOLogger,
502
+ LanguageEnvironmentAnalyzer,
503
+ LintAnalyzer,
504
+ ProgramFlowAnalyzer,
505
+ RecursionRiskAnalyzer,
506
+ RedundancyAnalyzer,
507
+ TechnicalDebtAnalyzer,
508
+ UnusedVariableAnalyzer,
509
+ parse_cobol_with_expansion,
510
+ )
511
+ from cobolparser.analysis import (
512
+ HostVariableResolver,
513
+ IMSSegmentAnalyzer,
514
+ IOSequenceAnalyzer,
515
+ LinkageChecker,
516
+ MoveTypeChecker,
517
+ )
518
+ from cobolparser.analysis.field_lineage import FieldFlowAnalyzer
519
+ from cobolparser.analysis.program_signature import extract_signatures
520
+ from cobolparser.analysis.sql_cics_lint import SqlCicsAnalyzer
521
+ from cobolparser.analysis.xref import XrefAnalyzer
522
+ from cobolparser.generators.data.layout_offsets import compute_program_data_items
523
+
524
+
525
+ def load(path):
526
+ with open(path) as f:
527
+ return parse_cobol_with_expansion(f.read(), path, copybook_paths=["copybooks"]).ast
528
+
529
+
530
+ ast = load("src/ORDPOST.cbl")
531
+
532
+ lint = LintAnalyzer().analyze(ast) # every checker below, in one pass
533
+ for finding in lint.findings:
534
+ print(finding.rule, finding.severity, finding.location, finding.message)
535
+
536
+ DeadCodeAnalyzer().analyze(ast) # dead-code
537
+ UnusedVariableAnalyzer().analyze(ast) # unused-variables
538
+ flow = ProgramFlowAnalyzer().analyze(ast) # program-flow
539
+ RecursionRiskAnalyzer().analyze(ast) # recursion-check
540
+ ComplexityAnalyzer().analyze(ast) # complexity
541
+ TechnicalDebtAnalyzer().analyze(ast) # health
542
+ RedundancyAnalyzer().analyze(ast) # redundancy
543
+ IOSequenceAnalyzer().analyze(ast) # io-sequence
544
+ MoveTypeChecker().check(ast) # move-type-check
545
+ XrefAnalyzer().analyze(ast) # xref
546
+ FieldFlowAnalyzer().analyze(ast) # lineage
547
+ compute_program_data_items(ast) # data-items
548
+ IOLogger().analyze(ast) # every file operation, in order
549
+ CRUDMatrixGenerator().analyze(ast) # which file or table each program creates/reads/updates/deletes
550
+ DynamicCallAnalyzer().analyze(ast) # analyze: annotates each CALL with its possible targets
551
+
552
+ LinkageChecker().check(load("src/POSTDOM.cbl")) # linkage-check
553
+ print(extract_signatures(load("src/POSTDOM.cbl"))[0].to_dict()) # program-signature
554
+ BusinessRuleExtractor().analyze(load("src/ORDVAL.cbl")) # business-rules
555
+
556
+ db2 = load("src/DB2BATCH.cbl")
557
+ SqlCicsAnalyzer().analyze(db2) # sql-cics-check
558
+ DclgenChecker().check(db2) # dclgen-check
559
+ HostVariableResolver().resolve(db2) # each SQL host variable -> its data item
560
+ LanguageEnvironmentAnalyzer().analyze(load("src/LESERV.cbl")) # language-env
561
+ IMSSegmentAnalyzer().analyze(load("src/IMSMPP.cbl")) # ims-dli
562
+ ```
563
+
564
+ Flowcharts and diffs:
565
+
566
+ ```python
567
+ from cobolparser import ProgramFlowAnalyzer, parse_cobol
568
+ from cobolparser.analysis.ast_diff import ProgramDiffer
569
+ from cobolparser.generators import DotFlowchartGenerator, MermaidFlowchartGenerator
570
+
571
+ ast = parse_cobol("src/ORDPOST.cbl").ast
572
+ flow = ProgramFlowAnalyzer().analyze(ast)
573
+ print(MermaidFlowchartGenerator().generate(flow))
574
+ dot = DotFlowchartGenerator().generate(flow)
575
+
576
+ diff = ProgramDiffer().diff(parse_cobol("old/ORDPOST.cbl").ast, ast)
577
+ print(diff.to_text())
578
+ ```
579
+
580
+ ### Analyze a codebase
581
+
582
+ ```python
583
+ from glob import glob
584
+
585
+ from cobolparser.analysis.call_interface import CallInterfaceChecker
586
+ from cobolparser.analysis.codebase import CodebaseGraphBuilder, CopybookImpactAnalyzer
587
+ from cobolparser.analysis.field_lineage import FieldFlowAnalyzer
588
+ from cobolparser.analysis.field_widening import FieldWideningAnalyzer
589
+ from cobolparser.analysis.lineage_graph import LineageGraph
590
+ from cobolparser.analysis.lineage_jcl import bindings_from_jobs, load_jobs
591
+ from cobolparser import parse_cobol_with_expansion
592
+
593
+ programs = sorted(glob("src/*.cbl"))
594
+
595
+ graph = CodebaseGraphBuilder(copybook_paths=["copybooks"]).build(programs)
596
+ print(graph.callers_of("ORDVAL")) # codebase-graph
597
+ print(graph.to_mermaid())
598
+
599
+ impact = CopybookImpactAnalyzer(graph).analyze("ORDREC") # copybook-impact
600
+ print(impact.direct_programs)
601
+
602
+ calls = CallInterfaceChecker(copybook_paths=["copybooks"]).check_files(programs)
603
+ print(calls.to_text()) # call-check
604
+
605
+ # field-impact and widen-check: one lineage graph over every program and the JCL
606
+ flows = []
607
+ for path in programs:
608
+ with open(path) as f:
609
+ ast = parse_cobol_with_expansion(f.read(), path, copybook_paths=["copybooks"]).ast
610
+ flows.append(FieldFlowAnalyzer().analyze(ast))
611
+ jobs, errors = load_jobs(glob("jcl/*.jcl"), proc_path="proclib")
612
+ bindings, passthroughs = bindings_from_jobs(jobs)
613
+ lineage = LineageGraph(flows, bindings, passthroughs)
614
+
615
+ print(lineage.impact("ORD-AMT", direction="forward")) # field-impact
616
+ widen = FieldWideningAnalyzer(lineage).analyze("ORD-CUST-ID", "9(10)")
617
+ for finding in widen.findings: # widen-check
618
+ print(finding.severity, finding.kind, finding.program, finding.message)
619
+ ```
620
+
621
+ ### Test data
622
+
623
+ ```python
624
+ from cobolparser.generators import (
625
+ Charset,
626
+ CopybookDataGenerator,
627
+ DataGeneratorOptions,
628
+ EncodingOptions,
629
+ ProgramFixtureGenerator,
630
+ RecordDecoder,
631
+ compare_files,
632
+ )
633
+
634
+ options = DataGeneratorOptions(rows=100, seed=7)
635
+ generator = CopybookDataGenerator(options)
636
+ dataset = generator.generate_from_file("copybooks/ORDREC.cpy", copybook_paths=["copybooks"])
637
+ dataset.write_csv("orders.csv") # gen-data
638
+
639
+ # A record image needs every byte (FILLER too): use the record-image options.
640
+ ebcdic = EncodingOptions(charset=Charset.EBCDIC)
641
+ image = CopybookDataGenerator(options.for_record_image()).generate_from_file(
642
+ "copybooks/ORDREC.cpy", copybook_paths=["copybooks"]
643
+ )
644
+ image.write_records("expected.dat", ebcdic) # gen-data --format record
645
+
646
+ decoder = RecordDecoder.from_copybook_file(
647
+ "copybooks/ORDREC.cpy", opts=ebcdic, copybook_paths=["copybooks"]
648
+ )
649
+ decoded = decoder.decode_file("expected.dat", max_records=5) # decode
650
+ print(decoded.to_csv())
651
+
652
+ result = compare_files(decoder, "expected.dat", "expected.dat", key=["ORD-ID"])
653
+ print(result.equal) # compare: True
654
+
655
+ bundle = ProgramFixtureGenerator().generate_with_scenarios_from_file(
656
+ "src/ORDPOST.cbl", copybook_paths=["copybooks"], mode="all", seed=7
657
+ ) # gen-fixtures
658
+ print([scenario.name for scenario in bundle.scenarios])
659
+ bundle.write_csv_dir("fixtures/")
660
+ ```
661
+
662
+ ### JCL, CICS, DB2 and IMS definitions
663
+
664
+ ```python
665
+ from pathlib import Path
666
+
667
+ from cobolparser.definitions import parse_definitions
668
+ from cobolparser.jcl import parse_jcl, resolve_dd_bindings
669
+
670
+ jcl = parse_jcl(Path("jcl/ORDNIGHT.jcl").read_text(), filename="ORDNIGHT.jcl", proc_paths=["proclib"])
671
+ for binding in resolve_dd_bindings(jcl): # jcl --bindings
672
+ print(binding.step, binding.ddname, binding.dataset)
673
+ print(jcl.steps_running("ORDPOST"))
674
+
675
+ ddl = parse_definitions(Path("defs/BANKDDL.ddl").read_text()) # DB2 DDL
676
+ print([table.name for table in ddl.tables])
677
+ ```
678
+
679
+ `parse_definitions` detects the kind itself and also reads CICS CSD
680
+ (`DEFINE PROGRAM/TRANSACTION/FILE ...`), BMS maps, and IMS DBD and PSB
681
+ sources (`parse_csd`, `parse_bms`, `parse_ddl`, `parse_dbd`, `parse_psb` for
682
+ one kind). The CLI has no subcommand for these; the MCP server and the
683
+ LegacyLens backend use them. Sample sources are in
684
+ [tests/samples/definitions/](tests/samples/definitions/).
685
+
686
+ ### LE catalogue, SARIF and project config
687
+
688
+ ```python
689
+ from pathlib import Path
690
+
691
+ from cobolparser import LintAnalyzer, parse_cobol
692
+ from cobolparser.analysis.sarif import lint_results, sarif_log
693
+ from cobolparser.config.project import load_project_config
694
+ from cobolparser.dialects.le_signatures import intrinsic_signature, le_service_signature
695
+
696
+ print(le_service_signature("CEEDAYS").to_dict()) # le-info CEEDAYS
697
+ print(intrinsic_signature("NUMVAL-C").to_dict())
698
+
699
+ report = LintAnalyzer().analyze(parse_cobol("src/ORDPOST.cbl").ast)
700
+ log = sarif_log(lint_results(report.to_dict(), "src/ORDPOST.cbl")) # lint --format sarif
701
+
702
+ config = load_project_config(Path.cwd()) # config: the cobol.yml in effect
703
+ print(config.source, config.copybook_path)
704
+ ```
705
+
706
+ The per-module reference, with every report field, is in the OKF topic
707
+ files ([.okf/analysis.md](.okf/analysis.md),
708
+ [.okf/generators.md](.okf/generators.md), [.okf/batch.md](.okf/batch.md),
709
+ [.okf/jcl.md](.okf/jcl.md), [.okf/definitions.md](.okf/definitions.md)).
710
+
711
+ ## Language coverage
712
+
713
+ IBM Enterprise COBOL through 6.4: fixed and free format, `COPY ... REPLACING`
714
+ and `REPLACE`, conditional compilation (`>>DEFINE`, `>>IF`, `>>EVALUATE`),
715
+ nested and contained programs, object-oriented `CLASS-ID` / `METHOD-ID`,
716
+ user-defined functions (`FUNCTION-ID`), DECLARATIVES, Report Writer, XML and
717
+ JSON statements, and `EXEC SQL`, `EXEC CICS` and `EXEC DLI` blocks. One
718
+ program per IBM program type (batch, VSAM, CICS, IMS, DB2, MQ, ...) runs
719
+ through the whole stack in the test suite; the matrix is in
720
+ [docs/enterprise-program-types.md](docs/enterprise-program-types.md).
721
+
722
+ ## Documentation
723
+
724
+ | For | Read |
725
+ |---|---|
726
+ | Using the MCP server | [docs/mcp-server.md](docs/mcp-server.md) |
727
+ | The `cobol.yml` project config | [docs/project-config.md](docs/project-config.md) |
728
+ | Linting COBOL in CI | [docs/ci-lint.md](docs/ci-lint.md) |
729
+ | The `gen-fixtures` bundle format | [docs/fixture-bundle-schema.md](docs/fixture-bundle-schema.md) |
730
+ | Every subcommand and flag | [.okf/cli.md](.okf/cli.md) |
731
+ | How the library works, area by area | [.okf/index.md](.okf/index.md) |
732
+ | What the backend and mocky-mock rely on | [interface-contract.md](interface-contract.md) |
733
+ | What changed in each release | [CHANGELOG.md](CHANGELOG.md) |
734
+ | Everything under `docs/`, including design plans | [docs/README.md](docs/README.md) |
735
+
736
+ The `.okf/` folder is the reference documentation: one topic file per area
737
+ (lexer, parser, analyzers, generators, CLI, MCP, tests), written so that a
738
+ person or an AI agent loads only the file for the task at hand.
739
+ `scripts/okf_check.py` checks what those files claim against the code.
740
+
741
+ ## Development
742
+
743
+ ```bash
744
+ pip install -e ".[dev,docs]"
745
+ git config core.hooksPath .githooks # the OKF pre-commit check
746
+
747
+ python -m pytest tests/ -q -n 4 --no-cov # fast full run
748
+ python -m pytest tests/ # with the 90% coverage floor
749
+ COBOLPARSER_PERF=1 python -m pytest tests/performance/test_large_program.py # 40k-line perf lane
750
+
751
+ python -m ruff check .
752
+ python -m black .
753
+ python -m mypy cobolparser/
754
+ ```
755
+
756
+ CI runs only on manual dispatch (`.github/workflows/ci.yml` has no push or PR
757
+ trigger), so run lint, types and the full suite locally before pushing. Measure coverage on
758
+ the pure-Python build: with `COBOLPARSER_ACCEL=1`, coverage.py cannot see the
759
+ code the compiled modules replace. Test layout and markers:
760
+ [.okf/tests.md](.okf/tests.md).
761
+
762
+ ## License
763
+
764
+ GNU Affero General Public License v3.0 or later. Copyright © 2026 Samuel Dion.
765
+ See [LICENSE](LICENSE).