Sublime Forum

Syntax Scoping Help: Class vs Instance

#1

I’m creating a syntax definition for Alan, an Interactive Fiction authoring language. I’m no syntax expert, but with the help of users from the forum I’m starting to make my way through scope name choices and best practices.

I’m implementing the sytnax constructs using arbitrary scope names until I understand which are the correct choices, and I’d like some help to fix the scope names before the project grows too much. My problem is mainly due to lack of experience on how to determine the right scope a syntax construct belongs to, as well as handling the scope name segments.

The Alan language is a class-based programming language, so the distinction between Class and Instance is significant (especially for plugins and scope selectors). Also, all instances are statically created at game-start, and no new instances can be created during play (ie dynamically).

So far, with help from this forum, I’ve managed to scope class declarations correctly. Where the declaration of a class being:

EVERY book IsA object.
  -- here go class-level attributes, verbs, checks, etc.
END EVERY book.

… is being scoped as:

EVERY book IsA object. -- comment
--^^^                  meta.class.alan    storage.type.class.alan
--             ^^^^^^  meta.class.alan    entity.other.inherited-class.alan
--                   ^ meta.class.alan    punctuation.terminator.alan
--    ^^^^             meta.class.alan    entity.name.class.alan
--         ^^^         meta.class.alan    storage.modifier.extends
END EVERY book.
-- ^^^^^^^^^^^^        meta.class.alan
--        ^^^^                            entity.name.class.tail.alan
--            ^                           punctuation.terminator.alan

Instance Construct

An instance will be declared with this syntax:

THE cake IsA object.
  -- here go instance-specific attributes, verbs, checks, etc.
END THE cake.

As a temporary solution I’ve scoped this way (just to get the job done):

THE cake IsA object. -- comment
--<-                   meta.instance.alan    storage.type.instance.alan
--           ^^^^^^    meta.instance.alan    entity.other.inherited-class.alan
--                 ^   meta.instance.alan    punctuation.terminator.alan
--  ^^^^               meta.instance.alan    entity.name.instance.alan
--       ^^^           meta.instance.alan    storage.modifier.extends
END THE cake.
-- ^^^^^^^^^^          meta.instance.alan
--      ^^^^                                 entity.name.instance.tail.alan
--          ^                                punctuation.terminator.alan

I’ve tried my best in reading docs from various sources, but the whole question of what an instance actually is seems to be at the center of a semantic debate in various languages. I seem to understand that at the end of the day it’s just a type of variable, but in this specific interactive fictions languages there are basically only classes, instances, attributes, verbs and events (plus a few native types like booleans, string, and sets), so if it’s not a big “no-no” I’d like to keep the word instance somehow.

At this project, I’ve found some real case uses of instance in scopes:

So I wanted to get some advice on which would the right choice balancing the benefits of sticking to standard scope names and the specific needs of the language package — eg, having the right scopes to handle things like autocompletion, and plugins that are specifically thought for this syntax. Being an interactive ficiton syntax, I doubt it might be making use of many plugins; and even for color schemes, since it’s a mixture of light-code and prose, dedicated color schemes are most likely the best choice.

The “ADD TO” Construct

Another syntax construct which I’ve already covered with temporary scope names is the ADD TO construct, which is used to change/add an already defined class (you can use all the same constructs as in a class declaration, except that the class must exists beforehand).

An example:

ADD TO EVERY toy
  -- some class-level additions and overrides (attributes, verbs, checks, etc.)
END ADD TO toy.

As a temporary solution, I’ve scoped the whole block as meta.addition.alan:

ADD TO EVERY toy
^^^^^^^^^^^^     storage.modifier.extends.alan
             ^^^ entity.name.class.alan
END ADD TO toy.
^^^^^^^^^^       keyword.control.alan
           ^^^   entity.name.addition.tail.alan

What meta scope should I use for this? It seems to me that it is a class construct after all, but I’d like to be able to distinguish it from a class declaration in scope-selectors.

Can I add an extra scope to both the class declaration block (eg: meta.class.declare) and to this one (eg: meta.class.extend) so that they share a common segment, but also can be distinguished one another?

Should the class identifiers here have a different class scope from the class declaration block (eg: entity.name.class.extend.alan)?

Thanks for your help.

0 Likes

#2

meta.instance/storage.type.instance looks reasonable for lack of a standard alternative.

I’d treat ADD TO like a partial class declaration. That is, ADD TO would get storage.modifier, and the rest of the declaration would be scoped as an ordinary class. (Can you ADD TO THE cake?)

To scope partial declarations more specifically, there are two options. You can try to specialize the meta scope to meta.class.partial or somesuch. This is easy if and only if ADD always signals the start of a partial class (with EVERY). If this is not the case, then you’re stuck with tricky and unreliable guesswork. Alternatively, you can introduce an enclosing meta.extension scope, so that a partial class would be meta.extension meta.class. This would be simpler to implement and more flexible to extend.

0 Likes

#3

Thanks @ThomSmith!

Can you ADD TO THE cake?

No, ADD TO EVERY only works for classes; also, there are no other uses of the ADD keyword in the language beside this specific use).

I tend to like more your first proposal, using meta.class.partial (or similar) rather than an extra enclosure like meta.extension meta.class, because the language already allows lots of nested constructs (eg: verbs can be declared at global level, but also inside classes and instances, and verbs can contain many nested conditional blocks — and I’ll need to scope them for autocompletion purposes); but I’ll have to ponder about what you said on the latter being “simpler to implement and more flexible to extend” (possibly, when the syntax grows I’ll get a clearer picture on this).

You’ve been again very helpful, I hope I can soon repay you somehow. In the meantime, I want to let you know that I had already added you to the Acknowledgment of the project a few day ago:

There are some constructs in this language for which I can’t find any paralllels in other languages (probably they are just very simple constructs disguised as natural language, but they are challenging when it comes to decide what they are). I’m trying to procrastinate the difficult ones as much as I can, but I’ll have to face them eventually. :frowning:

0 Likes