Agrega tu lenguaje

Enseña a este build a indexar un lenguaje que no trae, con una semilla en .orch/langs, y súbela al repo público cuando funcione.

Objetivo#

Que el índice de símbolos vea tu lenguaje. Veintinueve vienen embebidos; el trigésimo —un DSL interno, un dialecto, un lenguaje que nadie nos ha mandado— va en .orch/langs/<id>.json, al lado de los gates que escribes en .orch/gates/user/.

Mientras no exista una semilla, un archivo de ese lenguaje es un archivo que Orchemax no puede leer: search_shared_symbols no devuelve nada de él, el gate de duplicados no tiene qué comparar y trace_path se detiene en su borde.

La semilla#

Un documento JSON por lenguaje:

{
  "id": "cobol",
  "exts": [".cbl", ".cob"],
  "comment": "*>",
  "rules": [
    {
      "kind": "unit",
      "pattern": "(?mi)^\\s*PROGRAM-ID\\.\\s+([A-Z0-9-]+)",
      "name_group": 1
    },
    {
      "kind": "func",
      "pattern": "(?mi)^\\s*([A-Z0-9-]+)\\s+SECTION\\.",
      "name_group": 1
    }
  ]
}
Campo Significado
id El id del lenguaje. Si falta, se usa el nombre del archivo
exts Las extensiones que reclama. Una extensión ya reclamada por un lenguaje embebido se toma
comment Marcador de comentario de línea (//, #, --, *>) — lo que los gates de comentarios quitan antes de juzgar
aliases Otros nombres que resuelven a este lenguaje
rules Los patrones de declaración. Se omiten si el lenguaje tiene engine nativo
engine Solo go-ast, y solo Go lo usa: un parser real en vez de regexes
imposed_names Nombres de miembros que fija el lenguaje o su runtime — ver abajo
bom_required El compilador lee un archivo sin marca de orden de bytes en la code page heredada de la máquina — ver abajo

Una regla#

pattern es una regexp de Go que corre sobre cada archivo de ese lenguaje; name_group es la captura con el nombre declarado; kind lo etiqueta (func, type, unit, const, …).

params_group es la captura con la lista de parámetros, y es la diferencia entre comparar firmas y comparar nombres. Sin ella dos sobrecargas de un mismo nombre se normalizan al mismo texto: el gate de duplicados reporta duplicado en cada sobrecarga, y el consejo "esto ya existe en otro proyecto, promuévelo a shared" salta con homónimos. Veintiséis de las veintiocho semillas de regex embebidas la traen; shell y haskell no, porque ninguno declara parámetros en la línea que nombra la función, y una regla que no ve la lista la omite en vez de adivinar.

imposed_names son nombres que eligió el lenguaje, no el autor: Delphi libera recursos en Destroy y solo ahí, así que noventa clases con recursos son noventa Destroy, y eso es conformidad, no duplicación. Los nombres listados quedan exentos de la mitad del gate que compara nombres; la mitad que compara cuerpos sigue juzgándolos, porque dos destructores que liberan campos distintos se leen distinto.

bom_required es true para Delphi y para nada más de lo que viene. Delphi lee una unit sin marca de orden de bytes UTF-8 en la code page que tenga la máquina, así que un archivo con cualquier byte arriba de ASCII — cualquier alfabeto, no solo acentos — compila y manda cada uno de esos caracteres como dos. Con el flag puesto, orch guard encoding niega ese archivo y lo dice. Pónlo solo donde la cadena de herramientas se comporte así: una BOM es ruido en todo lo demás, y Go la rechaza de plano.

Instálala y compruébalo#

mkdir .orch/langs
# escribe .orch/langs/cobol.json
orch workspace
own languages: cobol (.cbl .cob) — from .orch/langs

Esa línea aparece solo cuando una semilla cargó. Después indexa y pide un símbolo:

orch index

Una semilla que no compila hace fallar la carga, y nombra el archivo y la regla:

language seed: C:\ws\.orch\langs\cobol.json: cobol rule 0: error parsing regexp: …

Nada más corre hasta arreglarla — una regex que nadie puede leer significa que el índice está mal para todos los archivos de ese lenguaje, y eso no es una condición silenciosa.

Sobrescribir un lenguaje que ya viene#

Usa el id con el que viene. La semilla reemplaza la embebida regla por regla en este taller, y así angostas un patrón demasiado suelto para tu código sin esperar un release.

Si solo quieres apuntar una extensión más a un lenguaje cuyas reglas ya sirven, no necesitas semilla — parsers en orch.yaml mapea extensión a un id existente:

parsers:
  .inc: php

Súbela al repo público#

Las semillas embebidas son una copia del langs/ del repositorio público orchemax-orch, y un test falla cuando las dos no coinciden. Una semilla que funciona en tu taller está a un PR de que la tenga todo el mundo: agrega langs/<id>.json, apendiza el id a langs/catalog.json y di en el PR si Orchemax debería embeberla. El CONTRIBUTING.md de allá tiene los pasos.

Relacionado#