Un lenguaje de marcas tipográfico en español, con compilador nativo a PostScript.
Cykaflex es un sistema de composición de documentos diseñado como alternativa hispanohablante a LaTeX. Su filosofía central es la separación estricta entre contenido y presentación: el autor escribe qué dice el documento en sintaxis Cykaflex (archivos .cyk), y el compilador decide cómo se ve, generando PostScript puro sin depender de pdflatex ni de ninguna distribución TeX.
Cykaflex es una aplicación multi-servicio contenedorizada con Docker. Cada componente vive en su propio contenedor y se comunica a través de una red interna de Docker Compose.
Cykaflex/
├── docker-compose.yml ← Orquestador: levanta ambos servicios
│
├── compiler-api/ ← Backend (Python · FastAPI) puerto 8000
│ ├── Dockerfile
│ ├── requirements.txt ← fastapi, uvicorn, ply, pandas
│ └── app/
│ ├── main.py ← Endpoints REST (/health /compile /tokenise /ast)
│ └── compiler/
│ ├── lexer.py ← Analizador léxico (ply.lex)
│ ├── parser_ll1.py ← Parser LL(1) predictivo recursivo
│ ├── ast_nodes.py ← AST — Patrón Composite
│ ├── codegen_postscript.py ← Generador PS — Patrón Visitor
│ └── __init__.py ← Exporta compile_to_ps()
│
└── web-editor/ ← Frontend (React 18 · Vite 6) puerto 3000
├── Dockerfile
└── src/
├── App.jsx ← Raíz: layout dividido + estado global
├── hooks/useCompile.js ← Debounce 1 s + AbortController
└── components/
├── Toolbar.jsx ← Barra de herramientas con gestión de archivos
├── CykaflexEditor.jsx ← Monaco Editor con resaltado personalizado
├── PreviewPanel.jsx ← Visor PDF (iframe) o PS (pre)
├── ErrorConsole.jsx ← Consola de errores estilo terminal
└── StatusBar.jsx ← Barra de estado inferior
El núcleo del sistema es un compilador de cuatro fases escrito en Python puro:
| Fase | Módulo | Tecnología | Rol |
|---|---|---|---|
| Análisis Léxico | lexer.py |
ply.lex |
Convierte el texto fuente en un flujo de tokens (7 símbolos + 23 keywords) |
| Análisis Sintáctico | parser_ll1.py |
LL(1) recursivo descendente | Valida la gramática y construye el AST |
| AST | ast_nodes.py |
Patrón Composite | 10 tipos de nodos tipados con @dataclass |
| Generación de Código | codegen_postscript.py |
Patrón Visitor | Emite PostScript-Adobe 3.0 válido, sin pdflatex |
La API REST está expuesta con FastAPI + Uvicorn y ofrece:
GET /health— verificación de livenessPOST /compile— código fuente → PostScript (+ conversión a PDF vía Ghostscript)POST /tokenise— depuración: devuelve lista de tokensPOST /ast— depuración: devuelve el AST en JSON
Interfaz de usuario retro-moderna inspirada en la estética NeXTSTEP / Windows 95, con fuentes del sistema, fondos #C0C0C0 y bordes biselados. Tecnologías clave:
- Monaco Editor con gramática Monarch personalizada para resaltado de sintaxis Cykaflex
- Renderizado en tiempo real: el hook
useCompiletiene un debounce de 1 000 ms y cancelación conAbortController - Panel dividido con resize por arrastre (20 %–80 %)
- Gestión de archivos
.cyk: abrir desde disco, editar el nombre y guardar el código fuente o la salida compilada
El motor no simula la justificación: inyecta una macro JustifyShow en el prólogo del PostScript generado. Esta macro usa stringwidth del intérprete para medir el ancho real de cada cadena y distribuir el espacio restante exactamente entre las palabras con widthshow. La última línea de cada párrafo se renderiza alineada a la izquierda para evitar el estiramiento antinatural.
El PostScriptVisitor mantiene contadores de estado internos. Las secciones se numeran automáticamente con dígitos arábigos (1., 2., …) y las subsecciones con letras mayúsculas (A., B., …), reiniciándose en cada nueva sección. El autor nunca escribe el número manualmente.
El comando texto acepta cualquier combinación de modificadores opcionales entre corchetes, en cualquier orden:
texto[14pt][negrita][cursiva]{"Texto con estilo combinado."}
El parser resuelve los modificadores en tiempo de análisis y el generador selecciona la variante tipográfica correcta:
| Combinación | Fuente PostScript |
|---|---|
| (ninguno) | Helvetica |
[negrita] |
Helvetica-Bold |
[cursiva] |
Helvetica-Oblique |
[negrita][cursiva] |
Helvetica-BoldOblique |
El prólogo de cada documento generado incluye una macro ReEncodeFont que re-registra las cuatro variantes de Helvetica bajo ISOLatin1Encoding, garantizando la correcta representación de caracteres como á, é, í, ó, ú, ñ y ¿/¡ en cualquier intérprete PostScript estándar.
- Docker y Docker Compose instalados.
# Clonar el repositorio
git clone <url-del-repositorio>
cd Cykaflex
# Construir las imágenes y arrancar los servicios
docker compose up --buildAbrir el navegador en http://localhost:3000.
Para arrancar en segundo plano:
docker compose up -d --buildVer logs de un servicio específico:
docker compose logs -f compiler-api
docker compose logs -f web-editor- Escribe o abre un archivo
.cyken el editor Monaco. - El documento se compila automáticamente cada segundo (debounce).
- El PDF renderizado aparece en el panel derecho en tiempo real.
- Usa ** Guardar .cyk** para guardar el código fuente.
- Usa ** Descargar Salida** para descargar el PDF o PostScript compilado.
| Token | Valor | Descripción |
|---|---|---|
cm |
cm |
Medida en centímetros |
pt |
pt |
Medida en puntos tipográficos |
inicio |
inicio |
Abre el bloque principal del documento |
fin |
fin |
Cierra el bloque principal |
documento |
documento |
Identificador del bloque raíz |
clasedocumento |
clasedocumento |
Declaración de clase de documento |
titulopagina |
titulopagina |
Título del documento |
capitulo |
capitulo |
Capítulo (sólo en tipo libro) |
seccion |
seccion |
Sección |
subseccion |
subseccion |
Subsección |
subsubseccion |
subsubseccion |
Subsubsección |
texto |
texto |
Párrafo de texto |
nuevapagina |
nuevapagina |
Salto de página explícito |
inicioe |
inicioe |
Lista enumerada |
inicioi |
inicioi |
Lista con viñetas |
item |
item |
Elemento de lista |
negrita |
negrita |
Estilo negrita |
cursiva |
cursiva |
Estilo cursiva |
| Patrón | Token |
|---|---|
{ |
LEFT_KEY |
} |
RIGHT_KEY |
[ |
LEFT_BRACKET |
] |
RIGHT_BRACKET |
"[^"]+" |
CONTENT |
[0-9]+ |
NUMBER |
%[^\n]* |
COMMENT (descartado) |
programa → clasedocumento bloque_documento
clasedocumento → CLASEDOCUMENTO [ NUMBER metrics ] { doc_type }
metrics → pt | cm
doc_type → articulo | libro
bloque_documento → inicio{documento} cuerpo fin{documento}
cuerpo → elemento cuerpo | ε
elemento → titulopagina | capitulo | seccion | subseccion
| subsubseccion | texto | lista | nuevapagina | COMMENT
texto → TEXTO modifier* { CONTENT }
modifier → [ NUMBER pt ] | [ negrita ] | [ cursiva ]
seccion → SECCION [ CONTENT ] { cuerpo }
subseccion → SUBSECCION [ CONTENT ] { cuerpo }
lista → enumerar | itemizar
enumerar → INICIOE [ ennumerar ] { items }
items → ITEM { CONTENT } items | ε
% Manifiesto de Cykaflex — ejemplo de todas las funcionalidades
clasedocumento[12pt]{articulo}
inicio{documento}
titulopagina[negrita]{"El Manifiesto de Cykaflex"}
seccion["El problema con la documentación actual"]{
texto{"Históricamente, la composición tipográfica de calidad ha sido territorio exclusivo de quienes dominan sistemas como LaTeX, una herramienta poderosa pero cuya curva de aprendizaje resulta empinada, en especial para usuarios hispanohablantes."}
texto[cursiva]{"Cykaflex nace de una pregunta simple: ¿puede un lenguaje de marcas ser al mismo tiempo expresivo, legible y en español?"}
}
seccion["Nuestros Principios"]{
subseccion["Separación de contenido y presentación"]{
texto{"El autor se ocupa del contenido. El compilador, de la forma. Esta separación reduce el ruido cognitivo y permite que los documentos evolucionen sin reescrituras masivas."}
}
subseccion["Tipografía de calidad, sin dependencias externas"]{
texto[14pt][negrita]{"Cykaflex genera PostScript puro."}
texto{"No invoca pdflatex, no requiere una distribución TeX. El compilador es autónomo y reproducible dentro de un contenedor Docker de menos de 150 MB."}
}
subseccion["Sintaxis diseñada para hispanohablantes"]{
texto{"Todos los keywords son palabras del español cotidiano: inicio, fin, seccion, negrita, cursiva. Leer un archivo .cyk es casi leer un guión."}
}
}
seccion["El Estado Actual"]{
texto{"El compilador implementa un analizador léxico basado en ply.lex, un parser LL(1) predictivo recursivo descendente, construcción de AST bajo el Patrón Composite y generación de código PostScript bajo el Patrón Visitor."}
texto[cursiva]{"La numeración de secciones y subsecciones es automática. La justificación del texto es perfecta gracias a macros nativas inyectadas en el prólogo PostScript."}
inicioe[ennumerar]{
item{"Análisis léxico: 7 símbolos + 23 keywords"}
item{"Análisis sintáctico: LL(1) recursivo descendente"}
item{"AST: 10 tipos de nodos (Patrón Composite)"}
item{"Generación de código: PostScript-Adobe 3.0 (Patrón Visitor)"}
}
}
nuevapagina
seccion["Cykaflex es un punto de partida"]{
texto[14pt][negrita][cursiva]{"Este documento fue escrito y compilado por Cykaflex."}
texto{"Cada sección numerada, cada párrafo justificado, cada carácter especial —á, é, ñ, ¿— es evidencia de que un compilador minimalista puede producir documentos tipográficos de calidad sin depender de sistemas externos."}
}
fin{documento}
La madurez de un sistema de software se mide también por la claridad con la que define sus límites. Cykaflex, en su versión actual, no soporta:
| Característica | Nota |
|---|---|
| Imágenes embebidas | No hay soporte para incluir gráficos o figuras en el documento. |
| Fórmulas matemáticas | No existe un modo matemático. Para ecuaciones complejas se requeriría un motor adicional (e.g., MathJax o un transpilador a PS). |
| Estilos en línea | El estilo (negrita, cursiva) aplica al bloque texto completo. No es posible marcar una palabra individual dentro de un párrafo. |
| Tablas | No hay comando para definir estructuras de tabla. |
| Referencias cruzadas | No existe un sistema de etiquetas (\label/\ref) para referenciar secciones o figuras. |
| Índices automáticos | No se genera tabla de contenidos ni índice analítico. |
| Fuentes personalizadas | El sistema está acoplado a la familia Helvetica Type-1. Fuentes externas requieren re-encoding manual en el prólogo PS. |
Estos puntos representan la hoja de ruta natural para futuras fases del proyecto.
- LaTeX Commands by NaSA
- Manual de LaTeX
- Engineering a Compiler — 3rd Edition, Keith D. Cooper & Linda Torczon
- TeX — LaTeX Stack Exchange
- Comprehensive TeX Archive Network (CTAN)
Cykaflex · Compilador tipográfico en español · PostScript nativo · Docker-first