feat(charka): PICTURE de edición — Z, coma de millares y punto decimal
El formateo de informes de COBOL: supresión de ceros a la izquierda, coma de millares e inserción del punto decimal. Rebanada vertical. - charka-lexer: el punto separador exige un espacio detrás; un punto pegado a un carácter (ZZ9.99) ya no es terminador, sino símbolo — el parser lo reensambla dentro de la cláusula PICTURE. - charka-runtime: format_edited(valor, pic) — 9, Z, coma, punto, B. - charka-ir: Field::edit guarda la PICTURE; el campo es texto. - charka-codegen / charka-shadow: MOVE a un campo de edición pasa por format_edited antes de almacenar. - Corpus: 19-reporte. Sombra y crate compilado dan la misma salida. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -149,8 +149,20 @@ fn lex_line(content: &str, line: u32, base_col: u32, out: &mut Vec<Token>) -> Re
|
||||
});
|
||||
i = next;
|
||||
} else if c == '.' {
|
||||
// El separador de sentencia COBOL siempre lleva un espacio
|
||||
// (o el fin de línea) detrás. Un punto pegado a un carácter
|
||||
// —`ZZ9.99`— no es separador: pertenece a una PICTURE de
|
||||
// edición y se emite como símbolo para que el parser lo
|
||||
// reensamble dentro de la cláusula.
|
||||
let is_separator = chars
|
||||
.get(i + 1)
|
||||
.map_or(true, |n| n.is_whitespace());
|
||||
out.push(Token {
|
||||
kind: TokenKind::Period,
|
||||
kind: if is_separator {
|
||||
TokenKind::Period
|
||||
} else {
|
||||
TokenKind::Symbol
|
||||
},
|
||||
text: ".".into(),
|
||||
line,
|
||||
col,
|
||||
@@ -329,6 +341,19 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn period_inside_an_edit_picture_is_not_a_separator() {
|
||||
// El punto de `ZZ9.99` va pegado a un dígito: es símbolo, no
|
||||
// terminador. El punto final, con espacio detrás, sí termina.
|
||||
let toks = kinds("PIC Z,ZZ9.99 .", SourceFormat::Free);
|
||||
let dots: Vec<TokenKind> = toks
|
||||
.iter()
|
||||
.filter(|(_, t)| t == ".")
|
||||
.map(|(k, _)| *k)
|
||||
.collect();
|
||||
assert_eq!(dots, vec![TokenKind::Symbol, TokenKind::Period]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_and_one_char_operators() {
|
||||
let toks = kinds("A <= B >= C <> D ** E + F", SourceFormat::Free);
|
||||
|
||||
Reference in New Issue
Block a user