Skip to main content

Register your language

rascal-0.42.0

Synopsis

Start a new VScode extension for your language

Description

We assume you have already written a Parsing Service function. Now think of:

  • a name for your language;
  • a file extension for its files.

We recommend write a module that focuses on registering your language:

module MyLanguageServer

import util::LanguageServer; ❶
import demo::lang::Pico::Syntax; ❷

start[Program] myParsingService(str s, loc l) { ❸
return parse(#start[Program], s, l);
}

set[LanguageService] myLanguageServices() { ❹
parser(myParsingService);
}

void main() { ❺
registerLanguage( ❻
language( ❼
pathConfig(), ❽
"Pico", ❾
{"pico"}, ❶⓿
"MyLanguageServer", ❶❶
"myLanguageServices" ❶❷
)
) ;
}
  1. Load the LSP API we need later
  2. Load the Syntax Definition needed for our Parsing Service
  3. Define a Parsing Service (could also be already define in the imported module)
  4. Collect all relevant language services. The function must not have positional parameters and return a set[LanguageService]. You can keep adding new services here to the set, and keep the other code the same.
  5. Having a main function is not obligatory, but when you deploy the extension later as an independent extension you will need it anyway.
  6. The call to Register Language does the final job of extending the current IDE with your own extension. A whole new Rascal runtime environment will be started just for your extension. Modules will be loaded, and the services will be connected to LSP callbacks, etc.
  7. The LanguageServer-language constructor provides five pieces of meta data:
  8. pathConfig is used to configure the Rascal runtime environment for loading your services. This comes in handy when you have third-party dependencies.
  9. This is the UI facing name of your language.
  10. These are the file extensions that activate the current IDE extension.
  11. This is the top module to import into the Rascal runtime environment for this extension.
  12. This is the name of the function in the top module which provides a set[LanguageService] when called with no arguments.

Then you simply call main() and you can open an editor with the file extension pico. The first time the parser will be generated and cached, and when it is finished Syntax Highlighting will show you the success of the parse.

That's it!

Now you can continue, for example, with Syntax Highlighting or Hover Service as two of the Language Server features to try out.

Benefits

  • repeated calls to Register Language re-initialize your language extension from scratch

Pitfalls

  • language extensions are not refreshed automatically if you change their implementation. You have to keep calling Register Language for this
  • (Accidental) console output, logging and unexpected error messages appear in VScode OUTPUT tabs, but these tabs are not automatically floating to the top. It's better to debug your services in the terminal.