This is basically a hybrid review of mitranim/sublime-rebol#1 and this repo. Decided to post it here since this is supposed to be the "base" syntax in the family. ๐
The syntax test file doesn't have to use //
for comments. It uses the characters preceding the SYNTAX TEST
pragma. It would be more conventional to use ;
here.
storage.string
for characters is very unconventional and not used by default syntaxes. Unless I misremember, the current guideline for character literals is to scope the entire literal as string
, and the content as constant.character
. There's some variation between languages, but this would be a good start with color scheme support.
The opening "
of character literals is scoped as storage.type
, and the closing "
isn't. This could result in different colors, depending on the color scheme. In any case, this isn't the conventional way to scope modified string literals. Check Python's raw strings; in r''
, the r
modifier gets storage.modifier
, while the rest is scoped without storage
.
The -
at the start of a number literal could receive an additional scope, like the dot in floats, but I'm not sure which...
#()
and #[]
delimiters have incorrect scopes. They use meta.X.begin
and meta.X.end
, which isn't the intended use for meta
. I believe these delimiters are analogous to literal data constructors like Type{}
in C/Go/Rust/Swift/etc., and should receive punctuation.section.X.begin/end
scopes.
Tags could benefit from some additional scopes. One decent option is to use conventional XML scopes, supported by many color schemes, for <
, tag
, >
, />
. My variation of the syntax does that.
Function parameters are normally supposed to be variable.parameter
. This is supported by many color schemes. I don't know how practical/important this is in Rebol/Red.
Refinements are scoped as entity.name
, which causes them to be indexed for symbol search and goto. Indexing seems useful for function refinements, but not useful for standalone refinements. If I understand correctly, refinement is a data type which isn't always a declaration (unlike set-word!
). It seems that refinements should be indexed only when used inside a function parameter list. They could use entity.name
in parameter lists and X
outside, or always X
with the addition of a meta scope and a .tmPreferences
configuration that causes them to be indexed in that scope. Unfortunately I don't know enough about refinements to define X
.
Some paths are incorrectly split into refinements.
Not sure if scoping as|to|make
in declarations as storage
is right. Their use seems to be analogous to the colon in var x: T
in many typed languages. It's more a keyword preceding a storage modifier, than a storage modifier itself.
This syntax hardcodes a large amount of "special" built-in words. Wouldn't be surprised if many of them were specific to Red. Perhaps they should be moved to a Red syntax?
Personally I'm not a fan of special-casing large amounts of built-in words, especially in a language like Rebol. We're meant to shape the language to our problem domain, and express the program with those higher-level abstractions. If a large proportion of the program consists of built-ins, it might be an indicator that we're still programming in "assembly language", not the higher-level language of our problem domain. This affects both regular functions and control flow constructs. I don't know how commonly Rebol/Red users define their own flow constructs, but in my Lisp experience, it was very common. In a language like this, special-casing only the built-in constructs can give a "second-class" feel to what you define yourself, which in my humble opinion goes against one of the core ideas of this language. This is highly subjective, and there isn't a clear "best" solution.