Skip to content

Repository files navigation

prism-raven

Prism syntax highlighting for the Raven programming language.

npm install @unkindnesses/prism-raven

Importing the package registers the grammar as raven, with rv as an alias:

import Prism from "prismjs"
import "@unkindnesses/prism-raven"

Prism.highlight(source, Prism.languages.raven, "raven")

Markup uses the usual language- class, so Prism.highlightAll() picks up:

<pre><code class="language-raven">fn square(x) { x * x }</code></pre>

To register on a different Prism instance — a bundler's copy, or prism-react-renderer — pass it in:

import { raven, register } from "@unkindnesses/prism-raven"

register(otherPrism)   // or use `raven` as a grammar directly

What it highlights

Raven has no reserved words. fn, if, while, for and bundle are macros, and a b c is just the macro a applied to b and c, so the grammar recognises the shape of a syntax block rather than a fixed word list — a user-defined macro highlights like a built-in one.

The rule that does the work is where a macro head may appear. A macro's arguments are parsed with syntax disabled, so in

for x = xs { show x }

for and show are heads but xs is not, even though it sits after an operator and before a block — brackets reset to statement level, which is why show gets to be a head again. At statement level the same shape is a macro:

ref = wasm call(support.identity): ref

Alongside that: line comments, strings in every delimiter form (including \"a "b" c"\ and triple quotes), template strings like r`\d` and tag"/Foo", @doc-style annotations, numbers, operators and calls. Inline JavaScript is handed to Prism's JavaScript grammar, with \name interpolation marked:

p = ```js
return new Promise(resolve => setTimeout(resolve, \n * 1000))
```

Token types are the standard Prism ones. Macro heads are keyword macro, string tags are string-tag function, and annotations are annotation symbol, so a theme can single them out without extra CSS.

Where it differs from the parser

Two deliberate departures, both because the alternative reads worse:

  • A word after a closing brace is highlighted as a keyword, which covers the else of an if and the from of an import. The parser treats both as arguments of the preceding macro.
  • A bare break, continue or return with no argument is highlighted, even though with nothing to apply to it is an ordinary identifier.

Tests

npm test

If a built Raven checkout is linked at ./raven, the suite additionally tokenizes every .rv file in it and checks the macro heads against the ones the real parser found, at the same offsets, along with the two departures above:

ln -s ../raven raven && (cd raven && npm run build)

Without it those cases skip and the rest of the suite runs unchanged.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages