Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending the TypeScript compiler for a DSL

Tags:

typescript

tsc

Before I start: yes I do need(/want) a DSL (even if it's just for the experience), there's no other format that expresses what I'm trying to do in a not-terribly-verbose, type-safe way.


Some background information, actual question at the bottom


I want to create a DSL-compiler for my project (TypeScript), and since the language shares a lot of syntax and concepts with TypeScript itself (I designed it that way) I thought of re-using parts of the TypeScript compiler to avoid re-inventing the wheel. I'm mostly interested in scanner, parser and binder. The other semantics and the emitting parts of my DLS differ so much from TypeScript that I'm pretty sure it'll be more efficient to write it from scratch.

I found this site which explains how the compiler actually works (although I'm pretty sure it's a little out of date), and so far I can understand everything pretty well. As far as I can see there are no reasons why I should reinvent the wheel if I can extend the TypeScript compiler.

The first part is of course the scanner. I tried to scan a file in my language to see what happens, turns out that everything tsc doesn't know about gets classified (SyntaxKind) as an Identifier (which makes sense). To implement my DLS I would have to add keywords and syntax types to this scanner to be sent to the parser for building an AST. I'll have to extend the parser as well of course, but that's not my concern right now.

My first instinct was to just clone the TypeScript respository and add the required logic. That way I could use the same API as on the aforementioned site, but with my added keywords/syntax/AST-nodes. I would then write the semantic checks and actually emitting the generated output from scratch, and all would be good.

Unfortunately that didn't really work (hence this question). The first roadblock was just being overwhelmed by the size and structure of the repository, I just didn't where I should look. I tried to create a little program that used the local source instead of the built one, but that didn't work either (probably due to some complicated pipeline tsc goes through before it's in any usable state). I did find the compiler.ts, parser.ts, etc. files, but without a way to use my custom version they weren't of much use. I tried to copy only the files I thought I'd need into my own project, but that caused all kinds of typing errors and missing functions and I have no idea how (and if) I should fix them. To make it even worse: certain files had actual compilation errors when I tried to compile them in my own environment (relaxing tsconfig.json settings didn't help).


Actual question

I have three questions:

  • Is it a good idea to try extend the parts of the TypeScript compiler which are useful, or should I just write from scratch? (I'm mainly talking about the scanner, parser and binder components.)
  • If I should just write from scratch, are there any tools for TypeScript/JavaScript that can help me with this (like ANTLR or javacc for Java)?
  • Are there any resources on how to implement a compiler in TypeScript/JavaScript except for the TypeScript compiler itself?
like image 349
superbadcodemonkey Avatar asked Mar 09 '19 13:03

superbadcodemonkey


1 Answers

After fiddling around a little longer I gave up on trying to extend the Typescript compiler. I ended up using chevrotain as a compiler-'generator', and so far it has been working ok.

The main disadvantage of this library is that it (in my experience) doesn't integrate very well with Typescript because there's a lot of "magic" stuff that was obviously designed to be used in the highly dynamic environment that is JavaScript (although the library itself is written in TS).

Overall I had a pretty pleasant experience with it. The documentation is very good, and there are a lot of possibilities. I can highly recommend it to anyone wanting to build a DSL in Typescript.

like image 154
superbadcodemonkey Avatar answered Oct 06 '22 22:10

superbadcodemonkey