@codincod/codemirror-lang-rexx
v0.1.1
Published
REXX language support for the CodeMirror code editor
Maintainers
Readme
@codincod/codemirror-lang-rexx 
[ CHANGELOG ]
This package implements REXX language support for the CodeMirror code editor, using a Lezer grammar written for this package.
CodeMirror has never shipped REXX, in either version. There was no CodeMirror 5 stream mode to port, so a REXX file in a browser editor has been plain text for as long as browser editors have existed.
Written in part for CodinCod, a competitive coding platform, where it colours the editor people solve puzzles in.
This code is released under an MIT license.
Usage
import {EditorView, basicSetup} from "codemirror"
import {rexx} from "@codincod/codemirror-lang-rexx"
const view = new EditorView({
parent: document.body,
doc: `say 'Hello World!'`,
extensions: [basicSetup, rexx()]
})For ooRexx, which reads -- as a comment:
rexx({dialect: "oorexx"})Coverage
ANSI REXX (X3.274-1996) and TRL 2, with the parts of Regina and ooRexx that
real programs use: -- line comments, the compound assignments += and their
relatives, /= for "not equal", LOOP, USE ARG, RAISE, FORWARD,
GUARD, REPLY, the ~ message operator and the ::CLASS directives. ARexx's
~ for not works as well, because the two never want it in the same place.
Instructions are parsed as themselves rather than as a generic statement, so
PARSE gets a template rather than an expression, DO gets its control
variable and limits, and SIGNAL ON ERROR NAME handler gets a condition and a
label. That is what gives folding a body to fold and indentation a block to
measure.
Measured against 1123 REXX files from Rosetta Code, 99.02% parse with no error
node. Eleven files fail, and almost none of them is REXX: four are missing the
/* that opened them, three are pseudo-code inside [square brackets], and the
rest is a NetRexx-flavoured include directive that classic REXX has no word
for.
Three things REXX does differently
Nothing is reserved. say = 1 assigns to a variable named say, end: is
a label, and x = if + 1 adds one to a variable named if. A word here is a
keyword only where the parser has room for that keyword, so the same word reads
as an instruction in one column and as a variable in the next.
A clause ends at the end of the line, unless the line ended with a comma,
which continues it. Runs of terminators are folded into one token, so a blank
line or a comment between then and else does not end the if.
Concatenation has no operator. say 'total:' n 'items' is three values
joined by the blanks between them. This is also why - needs care: after a
value it is subtraction, so end-1, end - 1 and end -1 are one expression,
while say -1 is a sign. REXX decides by position and so does this grammar.
What it gives an editor
Syntax highlighting, folding for DO and SELECT groups, indentation that
knows END closes a block and that WHEN sits inside its SELECT, and
completion for the instruction keywords, the TRL 2 built-in functions and the
trappable conditions.
rexxLanguage and ooRexxLanguage are exported for use with
LanguageSupport, and parser for use on its own.
Testing it on your own code
The grammar was developed against a corpus, and the script that measures it ships with the package:
node test/corpus.ts path/to/your/rexxIt prints the files that failed, the first line of each that did, and the proportion that came out clean. The corpus itself is not included; Rosetta Code is CC BY-SA and cannot be redistributed under this licence.
