Add your language
Teach this build to index a language it does not ship, with a seed under .orch/langs, and contribute it upstream when it works.
Goal#
Make the symbol index see your language. Twenty-nine ship embedded; a thirtieth —
an in-house DSL, a dialect, a language nobody has sent us yet — goes in
.orch/langs/<id>.json, beside the gates you write in .orch/gates/user/.
Until a seed exists for it, a file in that language is a file Orchemax cannot
read: search_shared_symbols returns nothing for it, the duplicate gate has
nothing to compare, and trace_path stops at its edge.
The seed#
One JSON document per language:
{
"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
}
]
}
| Field | Meaning |
|---|---|
id |
The language id. Defaults to the file name when omitted |
exts |
Extensions it claims. An extension already claimed by a shipped language is taken over |
comment |
Line-comment marker (//, #, --, *>) — what the comment gates strip before judging |
aliases |
Other names that resolve to this language |
rules |
The declaration patterns. Omit for a language with a native engine |
engine |
go-ast only, and only Go uses it: a real parser instead of regexes |
imposed_names |
Member names the language or its runtime fixes — see below |
bom_required |
The compiler reads a file with no byte-order mark in the machine’s legacy code page — see below |
A rule#
pattern is a Go regexp run over every file
of that language; name_group is the capture holding the declared name;
kind labels it (func, type, unit, const, …).
params_group is the capture holding the parameter list, and it is the
difference between comparing signatures and comparing names. Without it two
overloads of one name normalize to the same string, so the duplicate gate reports
a duplicate for every overload, and "this exists in another project, promote it to
shared" fires on homonyms. Twenty-six of the twenty-eight shipped regex seeds
carry one; shell and haskell do not, because neither declares parameters in
the line that names the function, and a rule that cannot see a parameter list
omits it rather than guessing.
imposed_names are names the language chose, not the author: Delphi frees
resources in Destroy and only there, so ninety classes with resources means
ninety Destroy, which is conformance and not duplication. Names listed here are
exempt from the name half of the duplicate gate; the similar-body half still
judges them, because two destructors that free different fields read differently.
bom_required is true for Delphi and for nothing else that ships. Delphi reads a
unit with no UTF-8 byte-order mark in whatever code page the machine runs, so a
file holding any byte above ASCII — any script, not only accents — compiles and
ships every one of those characters as two. With the flag set,
orch guard encoding denies that file and says so. Set it only where the toolchain really
behaves this way: a BOM is noise everywhere else, and Go rejects one outright.
Install it and check#
mkdir .orch/langs
# write .orch/langs/cobol.json
orch workspace
own languages: cobol (.cbl .cob) — from .orch/langs
That line appears only when a seed loaded. Then index and ask for a symbol:
orch index
A seed that will not compile fails the load, naming the file and the rule:
language seed: C:\ws\.orch\langs\cobol.json: cobol rule 0: error parsing regexp: …
Nothing else runs until it is fixed — a regex nobody can read means the index is wrong for every file of that language, and that is not a quiet condition.
Override a language that already ships#
Use the id it ships under. The seed replaces the shipped one rule for rule for this workshop, which is how you narrow a pattern that is too loose for your codebase without waiting for a release.
To point one more extension at a language whose rules are already right, you do
not need a seed at all — parsers in orch.yaml maps an extension onto an
existing id:
parsers:
.inc: php
Send it upstream#
The embedded seeds are a copy of the public
orchemax-orch repository's
langs/, and a test fails when the two disagree. A seed that works in your
workshop is one PR away from being one everybody gets: add
langs/<id>.json, append the id to langs/catalog.json, and say in the PR
whether Orchemax should embed it. CONTRIBUTING.md there has the steps.
Related#
- Your own rules — the gates you write, in the same
.orch/folder. - Languages and guards — the twenty-nine that ship today.
- Code graph — what the index is for once your language is in it.