STXT-SPEC-DRAFT
STXT (Semantic Text) — Core Language Specification
Category: Standards Track
Status: Draft
Format: Markdown (RFC-style)
1. Introducción
Este documento define la especificación del lenguaje STXT (Semantic Text).
STXT es un lenguaje Human-First, diseñado para que su forma natural sea legible, clara y cómoda para las personas, manteniendo al mismo tiempo una estructura precisa y fácilmente procesable por máquinas.
STXT es un formato textual jerárquico y semántico orientado a:
- Representar documentos y datos de manera clara.
- Ser extremadamente sencillo de leer y escribir.
- Ser trivial de parsear en cualquier lenguaje.
- Permitir tanto contenido estructurado como texto libre.
- Extender su semántica mediante
@stxt.schema.
Este documento describe la sintaxis base del lenguaje.
2. Terminología
Las palabras clave "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", y "MAY" deben interpretarse según RFC 2119.
3. Codificación del Documento
Los documentos STXT SHOULD codificarse en UTF-8 sin BOM.
Un parser:
- MAY aceptar documentos que comiencen con BOM.
- SHOULD emitir una advertencia si aparece.
4. Unidad Sintáctica: Nodo
Cada línea no vacía del documento que no sea comentario ni parte de un bloque >> define un nodo.
Existen dos formas de nodo:
-
Nodo simple o contenedor
Nombre: ValorInline -
Nodo de bloque textual (
>>)Nombre >> línea 1 línea 2
Un nodo puede incluir opcionalmente un namespace:
Nombre (@namespace):
Nombre (@namespace) >>
4.1 Normalización del nombre del nodo
El nombre del nodo se toma a partir del texto comprendido entre:
- El primer carácter no perteneciente a la indentación, y
- El primer carácter que pertenezca a cualquiera de:
- El inicio de un namespace
(, - El carácter
:, - El operador
>>, - O el fin de línea.
- El inicio de un namespace
Sobre ese fragmento se aplica:
- Eliminación de espacios y tabuladores iniciales (trim a la izquierda).
- Eliminación de espacios y tabuladores finales (trim a la derecha).
El resultado de esta normalización es el nombre lógico del nodo.
Un nodo cuyo nombre lógico sea la cadena vacía ("") es inválido y MUST provocar un error de parseo.
Ejemplos equivalentes a nivel de nombre:
Nombre: valor
Nombre : valor
Nombre: valor
Nombre : valor
Nombre (@ns):
Nombre(@ns):
Nombre >>
Nombre>>
5. Nodos con : (inline o contenedor)
La forma con : define un nodo que:
-
Puede tener valor inline (opcional).
-
Puede no tener valor inline (nodo vacío).
-
Puede tener hijos (nodos anidados).
-
Su contenido estructurado incluye:
- La propia línea del nodo.
- Sus descendientes con mayor indentación que no formen parte de bloques
>>.
Ejemplos:
Titulo: Informe
Autor: Joan
Nodo:
Nodo: Valor
Nodo:
SubNodo: 123
6. Nodos con >> (bloque textual)
La forma con >> define un bloque de texto literal.
Ejemplos válidos:
Descripcion >>
Línea 1
Línea 2
Seccion>>
Acepta el operador sin espacio
6.1 Reglas formales
-
La línea del nodo
>>MUST NOT contener contenido significativo tras>>, excepto espacios opcionales. -
Todas las líneas con indentación estrictamente mayor que la del nodo
>>pertenecen al contenido textual del bloque. -
Dentro del bloque:
- El parser MUST NOT interpretar ninguna línea como nodo estructurado, aunque contenga
:u otra sintaxis de STXT. - El parser MUST NOT interpretar líneas que comienzan por
#como comentarios; todas las líneas son texto literal.
- El parser MUST NOT interpretar ninguna línea como nodo estructurado, aunque contenga
-
El bloque termina cuando aparece una línea no vacía cuya indentación es menor o igual que la indentación del nodo
>>. -
Las líneas vacías dentro del bloque se conservan tal cual y MUST NOT cerrar el bloque, independientemente de su indentación.
Nota: la eliminación de líneas vacías finales del bloque se describe en la sección 10.3.
6.2 Ejemplo
Bloque >>
Texto
Hijo: valor SI permitido, es texto, no se parsea
Otro hijo: SI permitido
# Esto también es texto
SiguienteNodo: valor
En este ejemplo:
- Todo lo indentado por debajo de
Bloque >>es texto literal. Hijo: valoryOtro hijo: SI permitidono son nodos, sino texto.SiguienteNodo: valorestá fuera del bloque>>.
7. Namespaces
Un namespace es opcional y se especifica así:
Nodo (@com.example.docs):
Reglas:
- Un namespace MUST empezar por
@. - SHOULD usar formato jerárquico (
@a.b.c). - Se hereda por los nodos hijos.
- El namespace por defecto es
@stxt. - Un nodo hijo puede redefinir su namespace indicando (@otro.namespace), en cuyo caso usa ese namespace en lugar del heredado.
8. Indentación y Jerarquía
La indentación define la jerarquía estructurada del documento.
8.1 Indentación Permitida
Un documento STXT:
-
MAY usar únicamente espacios o únicamente tabuladores.
-
MUST NOT mezclarlos.
-
Si usa espacios:
- MUST usar exactamente 4 espacios por nivel.
-
Si usa tabs:
- Cada tab representa exactamente 1 nivel.
8.2 Jerarquía
- La indentación MUST aumentar de forma consecutiva (no se permiten saltos).
- Los nodos hijos MUST tener mayor indentación que su padre.
- La indentación dentro de un bloque
>>no afecta a la jerarquía estructural: es simplemente texto.
9. Comentarios
Fuera de bloques >>, una línea es un comentario si, tras su indentación, el primer carácter es #.
Ejemplo:
# Comentario raíz
Nodo:
# Comentario interior
9.1 Comentarios dentro de bloques >>
Dentro de un bloque >>:
-
Toda línea con indentación igual o superior a la indentación mínima del contenido del bloque MUST tratarse como texto literal, incluso si empieza por
#. -
Una línea menos indentada que el bloque termina el bloque y puede ser:
- Un comentario, si empieza por
#. - Un nodo estructurado.
- Un comentario, si empieza por
Ejemplo:
Documento:
Texto >>
# Esto es texto
Línea normal
# También es texto
# Esto sí es comentario
10. Normalización de espacios en blanco
Esta sección define cómo deben normalizarse los espacios en blanco para garantizar que distintas implementaciones produzcan la misma representación lógica a partir del mismo texto STXT.
10.1 Valores inline (:)
Al parsear un nodo con ::
-
El parser toma todos los caracteres desde inmediatamente después de
:hasta el fin de línea. -
El valor inline MUST normalizarse aplicando:
- Eliminación de espacios y tabuladores iniciales (trim a la izquierda).
- Eliminación de espacios y tabuladores finales (trim a la derecha).
Esto implica que las siguientes líneas son equivalentes a nivel de parseo:
Nombre: Joan
Nombre: Joan
Nombre: Joan
Nombre: Joan
En todos los casos, el valor lógico del nodo Nombre es "Joan".
Si tras el trim el valor queda vacío, el valor inline se considera la cadena vacía ("").
10.2 Líneas dentro de bloques >>
Para cada línea que pertenece a un bloque >>:
- El parser determina el contenido de la línea a partir del texto que sigue a la indentación mínima del bloque (es decir, elimina solo la indentación de bloque, pero conserva cualquier indentación adicional como parte del texto).
- Sobre ese contenido, el parser MUST eliminar todos los espacios y tabuladores finales (trim a la derecha).
Ejemplo de canonicalización de líneas:
Bloque >>
Hola
Mundo
Representación lógica del contenido del bloque:
- Línea 1:
"Hola" - Línea 2:
" Mundo"(las 4 espacios adicionales tras la indentación mínima se conservan, los espacios del final se eliminan)
10.3 Líneas vacías en bloques >>
- Las líneas vacías intermedias dentro del bloque (es decir, entre líneas no vacías) MUST preservarse como líneas vacías (
"") en la representación lógica del texto. - Tras leer todas las líneas de un bloque
>>, las implementaciones MUST eliminar las líneas vacías consecutivas al final del bloque (si las hubiera).
En otras palabras:
- Las líneas en blanco no cierran el bloque.
- No se conservan “saltos de línea sueltos” al final del bloque a nivel lógico.
Ejemplo:
Texto >>
Línea 1
Línea 2
Contenido lógico del bloque:
- Línea 1:
"Línea 1" - Línea 2:
"" - Línea 3:
"Línea 2"
Las líneas vacías finales después de "Línea 2" se eliminan en la representación lógica.
10.4 Normalización del nombre del nodo
La normalización del nombre del nodo ya se define formalmente en la sección 4.1. Como recordatorio operativo:
- Antes de interpretar
:o>>, el parser MUST obtener el nombre lógico aplicando la normalización descrita en 4.2. - Esto implica eliminar espacios y tabuladores a izquierda y derecha del fragmento que constituye el nombre.
- Distintas variantes con espacios siguen produciendo el mismo nombre lógico.
Ejemplo recordatorio:
Nombre: valor
Nombre : valor
Nombre : valor
En los tres casos, el nombre lógico del nodo es "Nombre".
11. Reglas de Error
Un documento es inválido si ocurre alguna de estas condiciones:
- Mezcla de espacios y tabuladores.
- Espacios que no sean múltiplos de 4 (cuando se usan espacios para indentación).
- Saltos en los niveles de indentación.
- Un nodo
>>contiene contenido significativo inline en la misma línea que>>. - Un nodo no contiene ni
:ni>>. - Un namespace no empieza por
@. - Se usa
:y>>en la misma línea.
Un parser conforme MUST rechazar el documento.
12. Conformidad
Una implementación STXT es conforme si:
- Implementa la sintaxis descrita en este documento.
- Aplica las reglas estrictas de indentación y jerarquía.
- Interpreta correctamente nodos con
:y bloques>>. - Interpreta comentarios fuera de bloques
>>. - Trata todo lo dentro de bloques
>>como texto literal. - Aplica las reglas de normalización de espacios en blanco de la sección 10.
- Rechaza documentos inválidos según la sección 11.
13. Extensión de Archivo y Media Type
13.1 Extensión de Archivo
Los documentos STXT SHOULD usar la extensión:
.stxt
13.2 Media Type (MIME)
Media type oficial:
text/stxt
Alternativa compatible:
text/plain
14. Ejemplos Normativos
14.1 Documento válido
Documento (@com.example.docs):
Autor: Joan
Fecha: 03/12/2025
Resumen >>
Este es un bloque de texto.
Con varias líneas.
Config:
Modo: Activo
14.2 Bloque con líneas vacías
Texto>>
Línea 2
Contenido lógico del bloque:
"""Línea 2"
14.3 Comentarios dentro y fuera de bloques
Documento:
Cuerpo >>
# Esto es texto
Más texto
# Esto sí es comentario
14.4 Bloque con “pseudo-hijos” (válido)
Bloque >>
Texto
Hijo: valor SI permitido
Otro hijo: SI permitido
# Esto también es texto
Siguiente: Nodo
14.5 Inválido: mezcla de indentación
A:
B:
\t\tC: valor
15. Apéndice A — Gramática (Informal)
Nodo = Indent Nombre NamespaceOpt (InlineOpt | BlockOpt)
NamespaceOpt = "(" "@" Ident ")"
InlineOpt = ":" Esp? TextoInline?
BlockOpt = Esp? ">>"
TextoInline = cualquier contenido hasta el fin de línea
BloqueTexto = líneas indentadas (texto literal, no estructurado)
Comentario = Indent "#" Texto ; Solo fuera de bloques '>>'
# Regla esencial:
# - Dentro de un bloque '>>', cualquier línea con indentación >= la
# indentación mínima del bloque es texto.
# - Las líneas vacías nunca cierran el bloque.
# - Una línea no vacía con indentación <= la del nodo '>>' lo cierra.
Indent = (" ")* | ("\t")*
16. Apéndice B — Interacción con @stxt.schema
El sistema de schemas permite añadir validación semántica a documentos STXT sin modificar la sintaxis base del lenguaje.
El núcleo STXT no define cómo debe reaccionar una implementación: el comportamiento pertenece exclusivamente al sistema de schemas (STXT-SCHEMA-SPEC).
Un schema es un documento STXT cuyo namespace es:
@stxt.schema
y cuyo objetivo es definir las reglas estructurales, tipos de valor y cardinalidades de los nodos pertenecientes a un namespace concreto.
El núcleo STXT no interpreta estas reglas; únicamente define cómo se expresan y cómo se combinan mediante namespaces.
16.1. Asociación de un schema a un namespace
Para asociar un schema al namespace com.example.docs, se escribe un documento:
Schema (@stxt.schema): com.example.docs
Node: Documento
Childs>>
(1) Campo1
(?) Campo2
(*) Texto
Node: Campo1
Node: Campo2
Node: Texto
16.2. Aplicación a documentos STXT
Un documento que declare el mismo namespace:
Documento (@com.example.docs):
Campo1: valor
Texto: uno
Texto: dos
puede ser validado por una implementación que soporte schemas STXT:
- Validando la presencia de nodos según
Nodedel schema. - Validando tipos de valor (
TEXT,DATE,NUMBER, etc.). - Validando cardinalidades definidas en
Childs>>.
16.3. Independencia del núcleo
STXT MUST NOT imponer reglas semánticas provenientes de schemas. El sistema de schemas es un componente separado y opcional que opera sobre el STXT ya parseado.