
A Simple Compiler in JavaScript - mgechev
https://github.com/mgechev/tiny-compiler/blob/master/tiny.js
======
tomsmeding
Of course, the implemented language is simple enough, to accomodate this
simple implementation. Still, looks nice, the code is very clear, and the
comments are pretty good.

The syntax is of course very limited with a one-line lexer, so more
sophistocation here would somewhat expand the lexer, even though if it remains
centered around regexes (which it probably will), it can remain pretty small.

When expanding the language, the tree building code can probably stay pretty
small as well, if the syntax of your new constructs are chosen wisely. (I
foresee control structures as prefix operators, which will be interesting to
say the least.)

The evaluator and transpiler would complicate themselves significantly when
adding control structures to the language: I think the most code-expanding
task would be handling of not-directly evaluated code blocks. In the case of
conditionals, you can probably get away with the ?: operator, also seeing as
JS has the comma operator. But in the case of loops, you need a conpletely
different structure in the output; it would depend on the implementation
whether that stays small or not.

Of course, adding control structures is only useful if there's some way of
defining names, be it variables (producing an imperative language) or
recursion-capable functions (producing a functional language). It might be an
interesting exercise to see how far you can push this language while still
keeping the compiler under, say, 100 lines. :P

Protip if you do that: ditch the evaluator. A compiler doesn't need an
interpreter to compile. ;)

------
willtim
I think compiler implementation is a particular sweetspot for functional
languages. Here's a similar tiny example in Haskell:

[http://www.timphilipwilliams.com/posts/2014-05-22-the-
essenc...](http://www.timphilipwilliams.com/posts/2014-05-22-the-essence-of-
compilation.html)

~~~
pjmlp
When I did my degree, the older students were forbidden to use any language
from the Lisp, ML or Prolog families for the compiler design assignment as
that would be too easy.

As Java was just released by the time my class got to do the same assignment,
we ended up using Java with JavaCC and JJTree.

While not as easy as Lisp, ML or Prolog, it was still much easier than the
Jurassic yacc/lex that still prevails in some circles.

~~~
seanmcdirmid
You’d be surprised how much hand written recursive descent is dominant in
industry, and to be honest, I think it is often easier than using generator
magic.

Everyone who is into compilers and parsing should try recursive descent at
least once.

~~~
pjmlp
True, but it should only be done after getting a working compiler, to get good
error handling and messages.

From my experience most people don't use parser generator tools due to lack of
knowledge that they even exist.

~~~
seanmcdirmid
People don't use parser generator tools because you wind up doing more work
than needed to integrate it with the rest of your compiler. The reason to use
a parser generator is not for ease of use or rapid development (because they
are harder to use and slower to develop with) but for performance and
reliability.

The first one isn't such a big deal for most programming languages, the second
one is. Throw in better error handling and tricks like sub-file incremental
and/or heuristical compilation (for IDEs), and the generators don't make much
sense anymore.

~~~
pjmlp
That makes sense after having a language reaching 1.0 in production use.

Not so much when prototyping, when it isn't even clear if the language is
going to get any users beyond the design team.

~~~
seanmcdirmid
My last few languages have all been prototyped by hand, but they were all live
languages (with continuous re-parsing and interpretation), so I didn’t have
much choice :). I havent bothered with ANTLR since grad school.

------
prezjordan
Wow, excellent work! These are always super interesting to read.

A similar project: [https://github.com/thejameskyle/the-super-tiny-
compiler](https://github.com/thejameskyle/the-super-tiny-compiler)

------
mrspeaker
I thought it would be good to include the output of the example executions at
the bottom of the page... then I remembered i could just paste that in a
console - very cool!

A while back I started making a game in javascript called "BASIC Instincts"
that was going to be about finding clues in the world and typing in BASIC
programs from magazines to solve puzzles. The parser/interpreter was the most
fun part
([https://www.youtube.com/watch?v=GwBiJR_rj_w](https://www.youtube.com/watch?v=GwBiJR_rj_w))

------
tlrobinson
I did the same thing for a conference talk once, but also “golfed” each of the
4 components down to Tweet size (back in my day, Tweets were 140 characters):
[https://gist.github.com/tlrobinson/1257254](https://gist.github.com/tlrobinson/1257254)

Every programmer should implement a simple Lisp from scratch at least once,
just to understand compilers and interpreters aren’t magic.

------
tempodox
Nicely done. It demonstrates the principles comprehensibly with no extraneous
noise.

------
burlesona
This is really cool, thanks for posting this. I've always been vaguely curious
how compilers work, but have never set aside time to research it. This was a
great introduction, I have a better beginner's notion of how they work now :)

------
jayflux
if anyone found this interesting, i recommend reading
[http://lisperator.net/pltut/](http://lisperator.net/pltut/)

It called "How to implement a programming language" its in JS and its made by
the guy who's behind uglifyJS

------
endisukaj
... but why?

~~~
smallnamespace
Why not?

------
adtac
*interpreter/transpiler, not a compiler

~~~
tomsmeding
The interpreter is certainly an interpreter, but a transpiler is arguably also
a compiler, be it maybe with an easier target than most conventional
compilers. Assembly language and machine code are also languages you can
program in; in that sense you'd also have to call gcc a transpiler ;)

~~~
adtac
Indeed, every compiler is a transpiler: it transpiles into asm. But not every
transpiler is a compiler in the truest sense of the term. IMO only transpiling
to machine language qualifies as compiling.

But we're just arguing about semantics here :) My comment was more directed
towards the interpreter part of things.

~~~
sebazzz
> IMO only transpiling to machine language qualifies as compiling.

It is not black and white, compiling to IL or bytecode qualifies as compiling.
Perhaps compiling means compilation to a binary executable format?

~~~
pjmlp
Bytecode is machine language, specially on mainframes and computer
architectures up to early 80's.

It is all a matter how the CPU executes it, direct mapping of machine code
into gates, or micro-coded translation layer.

------
trygvis
Aaw, this would have been great if it didn't use `eval`, but just executed
`+`, `-` etc directly.

~~~
packetslave
It doesn't use the built-in eval(). There's a local function in the code named
"eval" that executes the operation -- not the best choice of names, really.

~~~
trygvis
Oops, guess I read it a bit too fast.

