Tercera etapa del transpilador: Program -> Ir. El PROCEDURE division pasa de sentencias con tokens crudos a un árbol de instrucciones tipadas. - lower(&Program) -> Ir: total y tolerante, nunca falla. La DATA division pasa tal cual y sirve de tabla de símbolos. - Stmt cubre MOVE, DISPLAY, ACCEPT, COMPUTE, ADD, SUBTRACT, MULTIPLY, DIVIDE, IF/ELSE/END-IF, PERFORM (fuera de línea, en línea, TIMES, UNTIL), GO TO, STOP RUN, GOBACK, EXIT, CONTINUE. - Expresiones de COMPUTE con precedencia y paréntesis (Pratt). Condiciones con comparadores símbolo/palabra, AND/OR/NOT y nombres de condición (nivel 88). - Delimita statements por palabras frontera (COBOL no los separa con un símbolo). Verbo no soportado -> Stmt::Unknown con tokens crudos. - Módulos: ast / kw / cursor / expr / stmt. 17 tests; fmt + clippy limpios. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5.2 KiB
modules/charka/ — Transpilador COBOL → Rust
Propósito. Modernizar sistemas COBOL legados transpilándolos a Rust con un runtime determinista y un validador en sombra (shadow validator) que compara la salida del original y la del transpilado. Es el módulo más grande del ecosistema — el parser COBOL completo (CICS, SQL embebido, dialectos IBM Enterprise) es un esfuerzo multi-mes.
Crates
| crate | tipo | rol |
|---|---|---|
charka-bcd |
lib | Aritmética decimal de punto fijo con semántica COBOL: Picture, Decimal, redondeo, ON SIZE ERROR |
charka-lexer |
lib | Tokenizador COBOL: formato fijo (tarjeta de 80 columnas) y libre |
charka-parser |
lib | Parser COBOL'85 (subconjunto): tokens → AST (Program) |
charka-ir |
lib | Representación intermedia: el AST con los statements del PROCEDURE ya tipados |
charka-bcd
COBOL no calcula en binario flotante: opera sobre campos decimales de
precisión fija (PIC S9(5)V99). Reproducir un programa COBOL exige
reproducir esa aritmética dígito a dígito.
Picture— parsea la cláusula PICTURE numérica (9,V,S,9(n)).Decimal— punto fijo exacto (mantissa: i128+scale); suma, resta y producto exactos; división con escala de resultado fija; redondeoTruncate/HalfUp;coercea unPicturecon detección de desbordamiento.- Determinista, sin dependencias de plataforma — mismo programa, mismos dígitos, en cualquier máquina.
charka-lexer
Primera etapa del pipeline: texto COBOL → secuencia de Token.
- Lexer tonto: no conoce keywords ni la cláusula
PICTURE— emiteWordpara todo identificador; la clasificación es del parser. - Tokens:
Word(con guiones internos,WORKING-STORAGE),Number(sin signo),String(comillas dobladas colapsadas),Period,Symbol(( ) , ; :y operadores+ - * / ** = < > <= >= <>). - Dos formatos: fijo (cols 1-6 secuencia, 7 indicadora, 8-72
código, 73-80 id) y libre. Comentarios por col 7 (
*//) o*inicial en formato libre. - Cada token lleva línea/columna 1-based.
LexErrortipado. - Limitación v1: sin continuación de literales entre líneas
(indicador
-).
charka-parser
Segunda etapa: tokens → AST. Alcance v1 — el esqueleto del programa.
parse(&[Token]) -> Result<Program, ParseError>.Program { program_id, data: Vec<DataItem>, paragraphs: Vec<Paragraph> }.- DATA division → árbol de
DataItem(level,name,picture,value,children). Reensambla la cláusulaPICTUREdesde sus tokens (S9(5)V99→S9(5)V99); anida por número de nivel (01 y 77 son raíces; 88 cuelga del ítem precedente). - PROCEDURE division →
Vec<Paragraph>, cadaParagraphcon susSentence(tokens crudos — sin parseo a nivel de statement). Las sentencias previas al primer encabezado van a un párrafo implícito de nombre "". - Tolerante: salta encabezados de
SECTION, entradasFD/SDy cláusulas de datos que no seanPICTURE/VALUE.ParseErrorsólo ante nivel inválido o dato sin nombre. - Limitación v1: no parsea statements, ni la ENVIRONMENT division, ni CICS / SQL embebido / dialectos IBM.
charka-ir
Tercera etapa: Program → Ir. Aquí se parsea cada Sentence cruda
(tokens) a statements tipados — el PROCEDURE division pasa de tokens a
árbol de instrucciones.
lower(&Program) -> Ir— total y tolerante, nunca falla.Ir { program_id, data: Vec<DataItem>, procedures: Vec<Procedure> }. El modelo de datos pasa tal cual (sirve de tabla de símbolos).Procedure { name, body: Vec<Stmt> }.StmtcubreMove,Display,Accept,Compute,Add/Subtract/Multiply/Divide,If,Perform,GoTo,StopRun,Goback,Exit,Continue.Expr— expresiones aritméticas con precedencia y paréntesis (Pratt:+ -<* /<**der.).Cond— comparaciones (símbolo o forma palabra) unidas porAND/OR/NOT, más nombres de condición (88).- Un verbo no soportado se conserva como
Stmt::Unknown { verb, tokens }— el lowering jamás aborta. - COBOL no separa statements con un símbolo: cada uno corta donde
empieza el verbo del siguiente. El parser usa palabras "frontera"
(verbos + terminadores
END-*/ELSE+ conectoresTO/GIVING...) para delimitar listas de operandos. - Fuera de alcance v1:
EVALUATE,STRING/UNSTRING, E/S de ficheros,PERFORM VARYING, CICS, SQL embebido.
Estado
charka-bcd (22 tests), charka-lexer (17 tests), charka-parser
(15 tests) y charka-ir (17 tests) implementados y verdes.
Pendiente — el resto del transpilador (Fase D del plan macro):
| crate pendiente | rol |
|---|---|
charka-codegen |
emisión de Rust |
charka-shadow |
validador en sombra (original vs transpilado) |
charka-runtime |
runtime determinista (sobre charka-bcd) |
Hito intermedio sugerido: subconjunto COBOL'85 puro antes de CICS/SQL.