mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-07 02:58:02 +00:00
Standalone COBOL processor following the markdown-processor.ts pattern: - No LanguageProvider modification — COBOL uses regex, not tree-sitter - No SupportedLanguages enum change — standalone processor pattern New files: - cobol-processor.ts — orchestrator (processCobol, isCobolFile, isJclFile) - cobol/cobol-preprocessor.ts — regex state machine extraction (~888 LOC) - cobol/cobol-copy-expander.ts — COPY statement expansion with circular detection - cobol/jcl-parser.ts — JCL job/step/DD extraction - cobol/jcl-processor.ts — JCL graph node creation Extraction produces: - Module nodes (PROGRAM-ID) - Function nodes (paragraphs) - Namespace nodes (sections) - Property nodes (data items) - CALLS edges (PERFORM intra-file, CALL cross-program) - IMPORTS edges (COPY statements) - CONTAINS edges (section → paragraph hierarchy) Pipeline integration: single processCobol() call in Phase 2.6 54 new tests (33 COBOL + 21 JCL), all 3889 tests pass.
186 lines
7.9 KiB
Markdown
186 lines
7.9 KiB
Markdown
# COBOL Regex Extraction
|
|
|
|
The `extractCobolSymbolsWithRegex()` function in `cobol-preprocessor.ts` performs single-pass, state-machine-driven extraction of all COBOL symbols. This document describes the state machine, line processing flow, and every regex pattern used.
|
|
|
|
## State Machine: Division Tracking
|
|
|
|
The extractor tracks which COBOL division is currently being processed. Division transitions are detected by the `RE_DIVISION` pattern.
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> null : Start of file
|
|
null --> identification : IDENTIFICATION DIVISION
|
|
identification --> environment : ENVIRONMENT DIVISION
|
|
environment --> data : DATA DIVISION
|
|
data --> procedure : PROCEDURE DIVISION
|
|
|
|
note right of identification
|
|
Extracts: PROGRAM-ID, AUTHOR, DATE-WRITTEN
|
|
end note
|
|
note right of environment
|
|
Extracts: SELECT ... ASSIGN ... (file declarations)
|
|
end note
|
|
note right of data
|
|
Extracts: FD entries, data items (01-77, 88), COPY
|
|
end note
|
|
note right of procedure
|
|
Extracts: paragraphs, sections, PERFORM, CALL,
|
|
ENTRY, MOVE, EXEC SQL/CICS
|
|
end note
|
|
```
|
|
|
|
## State Machine: Data Section Tracking
|
|
|
|
Within the DATA DIVISION, a secondary state machine tracks the current section to tag data items with their origin.
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> unknown : DATA DIVISION entered
|
|
unknown --> working_storage : WORKING-STORAGE SECTION
|
|
unknown --> linkage : LINKAGE SECTION
|
|
unknown --> file : FILE SECTION
|
|
unknown --> local_storage : LOCAL-STORAGE SECTION
|
|
working_storage --> linkage : LINKAGE SECTION
|
|
working_storage --> file : FILE SECTION
|
|
linkage --> working_storage : WORKING-STORAGE SECTION
|
|
file --> working_storage : WORKING-STORAGE SECTION
|
|
file --> linkage : LINKAGE SECTION
|
|
local_storage --> working_storage : WORKING-STORAGE SECTION
|
|
```
|
|
|
|
Within the ENVIRONMENT DIVISION, the `currentEnvSection` tracks whether we are in `INPUT-OUTPUT` or `CONFIGURATION` section. SELECT statement accumulation only occurs in `INPUT-OUTPUT`.
|
|
|
|
## Line Processing Flow
|
|
|
|
Each raw source line goes through this pipeline:
|
|
|
|
```
|
|
Raw line
|
|
|
|
|
v
|
|
Length < 7? ---------> Skip (flush pending if any)
|
|
|
|
|
v
|
|
Indicator col 7
|
|
|
|
|
+-- '*' or '/' -----> Comment: skip entirely
|
|
|
|
|
+-- '-' ------------> Continuation: append to pending line
|
|
|
|
|
+-- other ----------> Normal: flush pending, strip inline comments (|),
|
|
buffer as new pending logical line
|
|
```
|
|
|
|
After all lines are processed, the final pending line is flushed, along with any accumulated SELECT statement.
|
|
|
|
### Inline Comment Stripping
|
|
|
|
Enterprise COBOL (particularly Italian dialect) uses the pipe character `|` as an inline comment marker. Everything from `|` to end of line is stripped before processing.
|
|
|
|
### Patch Marker Handling
|
|
|
|
The `preprocessCobolSource()` function (run before extraction in the worker) replaces non-standard content in columns 1-6. Standard COBOL expects spaces or digit sequence numbers in this area. If any letter or `#` character is found, the entire sequence area is replaced with 6 spaces:
|
|
|
|
```
|
|
Before: mzADD MOVE WK-AMT TO WK-TOTAL
|
|
After: MOVE WK-AMT TO WK-TOTAL
|
|
```
|
|
|
|
This preserves exact line count for position mapping.
|
|
|
|
## Regex Pattern Reference
|
|
|
|
All patterns are compiled once as module-level constants and reused across calls.
|
|
|
|
### Division and Section Detection
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_DIVISION` | `\b(IDENTIFICATION\|ENVIRONMENT\|DATA\|PROCEDURE)\s+DIVISION\b` | Division boundary | `PROCEDURE DIVISION` |
|
|
| `RE_SECTION` | `\b(WORKING-STORAGE\|LINKAGE\|FILE\|LOCAL-STORAGE\|INPUT-OUTPUT\|CONFIGURATION)\s+SECTION\b` | Section boundary | `WORKING-STORAGE SECTION` |
|
|
|
|
### IDENTIFICATION DIVISION
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_PROGRAM_ID` | `\bPROGRAM-ID\.\s*([A-Z][A-Z0-9-]*)` | Program name | `PROGRAM-ID. BGTABFL` |
|
|
| `RE_AUTHOR` | `^\s+AUTHOR\.\s*(.+)` | Author metadata | `AUTHOR. D. Smith` |
|
|
| `RE_DATE_WRITTEN` | `^\s+DATE-WRITTEN\.\s*(.+)` | Date metadata | `DATE-WRITTEN. 2024-01-15` |
|
|
|
|
### ENVIRONMENT DIVISION
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_SELECT_START` | `\bSELECT\s+([A-Z][A-Z0-9-]+)` | File SELECT start | `SELECT MASTER-FILE` |
|
|
|
|
SELECT statements are accumulated across multiple lines until a period terminator is found, then parsed for ASSIGN, ORGANIZATION, ACCESS, RECORD KEY, and FILE STATUS clauses.
|
|
|
|
### DATA DIVISION
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_FD` | `^\s+FD\s+([A-Z][A-Z0-9-]+)` | File description | `FD MASTER-FILE` |
|
|
| `RE_DATA_ITEM` | `^\s+(\d{1,2})\s+([A-Z][A-Z0-9-]+)\s*(.*)` | Data item (01-77) | `05 WK-NAME PIC X(30)` |
|
|
| `RE_ANONYMOUS_REDEFINES` | `^\s+(\d{1,2})\s+REDEFINES\s+([A-Z][A-Z0-9-]+)` | Anonymous REDEFINES | `01 REDEFINES WK-REC` |
|
|
| `RE_88_LEVEL` | `^\s+88\s+([A-Z][A-Z0-9-]+)\s+VALUES?\s+(?:ARE\s+)?(.+)` | Condition name | `88 WK-ACTIVE VALUE "Y"` |
|
|
|
|
The trailing clauses of `RE_DATA_ITEM` are parsed by `parseDataItemClauses()` for PIC, USAGE, OCCURS, and REDEFINES.
|
|
|
|
### PROCEDURE DIVISION
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_PROC_SECTION` | `^ ([A-Z][A-Z0-9-]+)\s+SECTION\.\s*$` | Procedure section header | ` MAIN-LOGIC SECTION.` |
|
|
| `RE_PROC_PARAGRAPH` | `^ ([A-Z][A-Z0-9-]+)\.\s*$` | Paragraph header | ` PROCESS-RECORD.` |
|
|
| `RE_PERFORM` | `\bPERFORM\s+([A-Z][A-Z0-9-]+)(?:\s+THRU\s+([A-Z][A-Z0-9-]+))?` | PERFORM call | `PERFORM CALC-TAX THRU CALC-TAX-EXIT` |
|
|
| `RE_PROC_USING` | `\bPROCEDURE\s+DIVISION\s+USING\s+([\s\S]*?)(?:\.\|$)` | USING parameters | `PROCEDURE DIVISION USING WK-PARAM` |
|
|
| `RE_ENTRY` | `\bENTRY\s+"([^"]+)"(?:\s+USING\s+([\s\S]*?))?(?:\.\|$)` | ENTRY point | `ENTRY "SUBPROG" USING WK-DATA` |
|
|
| `RE_MOVE` | `\bMOVE\s+(CORRESPONDING\s+)?([A-Z][A-Z0-9-]+)\s+TO\s+([A-Z][A-Z0-9-]+)` | MOVE statement | `MOVE WK-NAME TO OUT-NAME` |
|
|
|
|
Note: `RE_PROC_SECTION` and `RE_PROC_PARAGRAPH` require exactly 7 spaces of leading indentation (COBOL area A starting at column 8). This is the standard COBOL paragraph indentation.
|
|
|
|
### All-Division Patterns
|
|
|
|
These patterns are checked regardless of current division:
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_CALL` | `\bCALL\s+"([^"]+)"` | External program call | `CALL "BGTABUP"` |
|
|
| `RE_COPY_UNQUOTED` | `\bCOPY\s+([A-Z][A-Z0-9-]+)(?:\s\|\.)` | COPY (unquoted) | `COPY CPSESP.` |
|
|
| `RE_COPY_QUOTED` | `\bCOPY\s+"([^"]+)"(?:\s\|\.)` | COPY (quoted) | `COPY "WORKGRID.CPY".` |
|
|
|
|
### EXEC Block Patterns
|
|
|
|
| Constant | Pattern | Purpose | Example Match |
|
|
|----------|---------|---------|---------------|
|
|
| `RE_EXEC_SQL_START` | `\bEXEC\s+SQL\b` | Start of EXEC SQL block | `EXEC SQL` |
|
|
| `RE_EXEC_CICS_START` | `\bEXEC\s+CICS\b` | Start of EXEC CICS block | `EXEC CICS` |
|
|
| `RE_END_EXEC` | `\bEND-EXEC\b` | End of EXEC block | `END-EXEC` |
|
|
|
|
EXEC blocks accumulate all lines between `EXEC SQL/CICS` and `END-EXEC`, then delegate to `parseExecSqlBlock()` or `parseExecCicsBlock()` for detailed extraction.
|
|
|
|
## Excluded Paragraph Names
|
|
|
|
The following names are excluded from paragraph detection to avoid false positives from division/section headers:
|
|
|
|
```
|
|
DECLARATIVES, END, PROCEDURE, IDENTIFICATION,
|
|
ENVIRONMENT, DATA, WORKING-STORAGE, LINKAGE,
|
|
FILE, LOCAL-STORAGE, COMMUNICATION, REPORT,
|
|
SCREEN, INPUT-OUTPUT, CONFIGURATION
|
|
```
|
|
|
|
Additionally, paragraph candidates containing `DIVISION` or `SECTION` as substrings are excluded.
|
|
|
|
## MOVE Skip List (Figurative Constants)
|
|
|
|
MOVE statements where the source is a figurative constant are skipped:
|
|
|
|
```
|
|
SPACES, ZEROS, ZEROES, LOW-VALUES, LOW-VALUE,
|
|
HIGH-VALUES, HIGH-VALUE, QUOTES, QUOTE, ALL
|
|
```
|
|
|
|
## Source Files
|
|
|
|
- `gitnexus/src/core/ingestion/cobol-preprocessor.ts` -- `preprocessCobolSource()`, `extractCobolSymbolsWithRegex()`, all regex constants
|