stz syntax highlighting

stz syntax highlighting
Photo by Kim R-K / Unsplash

For my own sanity, now that the examples are getting more complicated, I really needed some syntax highlighting support for the language.

I need it in two places - here in ghost, the blogging software I use, and in zed.dev the editor i'm using.

This was a bit of a side-exploration in to other tooling that I hadn't poked about in before. I started with Ghost trying to set up Prism.js erroneously believing that's how syntax highlighting worked in Ghost.

I dug and dug and dug and tried to modify the Prism object with my own language definition and nothing seemed to work. I set that aside and took a look at zed.dev instead.

Zed is (smartly?) integrated with git so that an extension you add can specify a grammar which is pointed to at a git address with a commit id. That meant using my local git repository instead of github for me because I just prefer it that way.

I use gitea and it's hidden inside my internal network. But I have most of it accessible via an SSO portal. Problem was - git doesn't know how to use redirects to SSO portals. So I had to rejig my network so that zed could use git to get the grammar.

tree-sitter is the parsing library that zed.dev uses because of its incremental parsing and language extensions. That sounded interesting to me so I set about writing a grammar for Smalltalk Zero.

A few lunchtimes later of frustration I had reached the conclusion that all the interesting stuff in the language are easy to implement with a recursive descent parser but hard to implement with an LR parser. Even things like keyword selectors are difficult to do and once working didn't integrate with zed properly.

Did I want to make a language server? heck no. Not yet anyway. I settled for giving tree-sitter the lexical elements of stz so that it could syntax highlight. The result:

I'm happy enough with that that I let sleeping dogs lie for now. It's enough to help me visually parse what's going on and that will aid me in writing examples.

Back to Ghost though. I realised that there is no actual syntax highlighting built in - or if there is it's so in the guts it's not accessible. You're meant to add on your own syntax highlighter. At this point I was annoyed at Prismjs (probably unjustly) so I tried Highlightjs instead.

This led me astray the same way I think Prismjs did - the CDN versions of these libraries are out of date! Once I got my own local copy of highlight working suddenly I could parse enough of stz that now I can syntax highlight the language:

public
// ---

range = { class |
  parameters: (of: number-t = int,),
  constants:  (scalar-class: of,),
  traits:     (sequenceable-t of: scalar-class,),
  variables:  (start: scalar-class, stop: scalar-class,}


/* creation */
[ start to: stop
| assert start == stop
  number-t, number-t -> range of: start
| {start: start, stop: stop} ]


/* iteration */
[ range do: block
| range, (scalar-class -> ø) -> ø
| assert: start ≤ stop
  start to: stop step: step do: block ]

This is retroactive. Previous blog posts now have some version of syntax highlighting going on. I will need to revisit all of this in the future when I write stzc (stz compiler) and if I want language server support in zed.dev.

Well, that was a frustrating distraction for my lunches and evenings for a few days. Now back to the fun bit - language design!