Background Introduction#
As we all know, MoonBit is currently a compiled language that requires a complete code structure to run code. I have always hoped that MoonBit could have an interpreter designed for quick testing and interactive programming like Python and JavaScript's REPL (Read-Eval-Print Loop), so I attempted to implement an interpreter for learning purposes.
Preparation Work#
To implement such an interpreter, I first searched for toolchains in the JavaScript ecosystem that allow customization of DSL (Domain-Specific Language).
I found the following popular toolchain projects:
- Lexer and Parser Tools: Convert custom syntax into executable code or AST.
- ANTLR: A powerful parser generator that can define syntax to generate parsers and lexers, capable of generating JavaScript parsers to handle DSL.
- PEG.js: A JavaScript parser generator based on parsing expression grammar, which generates lightweight parsers by defining grammar.
- Chevrotain: A fast and versatile JavaScript parser building library that provides finer control for constructing complex syntax rules. Compared to PEG.js, Chevrotain is more flexible and supports custom error messages and optimization operations.
- AST Processing: AST processing is crucial when building DSL and compiling or executing code.
- Acorn: A fast and lightweight JavaScript parser that can parse JavaScript source code to generate AST, suitable for DSL with JavaScript-like syntax.
- ESTree: The standard format for JavaScript AST, many parsers generate AST that follows this standard and can be generated as needed.
- Code Generation Tools: After parsing DSL and generating AST, target code or execution of DSL can be generated.
- Babel: A popular JavaScript compiler that uses a plugin mechanism to transform AST into different versions of JavaScript or other target code.
- ESCodegen: A JavaScript library that converts AST back to source code, capable of generating JavaScript or other code for DSL.
- Template Engines:
- Useful for generating templated code or configuration files from DSL.
- EJS/Handlebars/Mustache: Can map DSL semantics to templates to generate output code.
- Custom Interpreters: Implement interpreters that directly execute DSL semantics.
- Esprima: A JavaScript parsing library that can parse and run custom JavaScript code, suitable for embedding JavaScript logic in DSL.
- Nearley.js: A PEG-based parser generator that can generate parsers and create interpreters.
After some attempts, I ultimately chose Chevrotain as the library for building a parser based on JavaScript and TypeScript. It provides tools for creating custom syntax parsers, supporting everything from simple syntax parsing to complex context-sensitive parsing. Chevrotain is designed with performance in mind, implementing an efficient parsing process based on an LL(k) parser model.
Preparation of the Frontend Interface#
I previously came across a project called WebContainer, and the jsh on the homepage deeply attracted me.
Upon reviewing the source code of this official website, I found that it uses xterm.js.
Even VSCode is using it, so I made a simple configuration and created a beautiful frontend terminal.
This article focuses on the preparation for starting the project, and the next article will officially begin constructing the core of the interpreter.
Project address: https://github.com/oboard/moonrepl