Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

rescript-lang/syntax

Folders and files

NameName
Last commit message
Last commit date
May 28, 2023
Jul 31, 2020
Jun 24, 2022
Mar 6, 2023
Oct 31, 2022
Jul 21, 2022
Feb 24, 2023
Jun 18, 2022
Mar 6, 2023
Jun 13, 2022
Jun 16, 2022
Jun 16, 2022
Mar 6, 2023
Aug 12, 2020
Jun 24, 2022
Dec 27, 2022
Jun 11, 2022
Jul 3, 2022
Jul 3, 2022

Repository files navigation

⛔️ DEPRECATED ReScript Syntax

The ReScript syntax sources are now a part of the compiler repo (see https://github.com/rescript-lang/rescript-compiler/tree/master/res_syntax).

Please create any new issues or PRs directly in the compiler repo.

Contribute

Why

A detailed discussion by Jonathan Blow and Casey Muratori on why you would hand-roll a parser for a production quality programming language Discussion: Making Programming Language Parsers, etc

"One reason why I switched off these parser tools is that the promises didn't really materialize. The amount of work that I had to do change a yacc script from one language to a variant of that language was more than if I hand wrote the code myself. " J. Blow.

Setup & Usage (For Repo Devs Only)

Required:

  • OCaml 4.10 or later
  • Dune
  • Reanalyze
  • OS: macOS, Linux or Windows
git clone https://github.com/rescript-lang/syntax.git
cd syntax
opam install . --deps-only --with-test
make # or "dune build"

This will produce the three binaries rescript, tests and bench (with .exe extension on Windows).

We only build production binaries, even in dev mode. No need for a separate dev binary when the build is fast enough. Plus, this encourages proper benchmarking of the (production) binary each diff.

After you make a change:

make

Run the core tests:

make test

Run the extended tests (not fully working on Windows yet):

make roundtrip-test

Those will tell you whether you've got a test output difference. If it's intentional, check them in.

Debug a file:

# write code in test.res
dune exec -- rescript test.res # test printer
dune exec -- rescript -print ast test.res # print ast
dune exec -- rescript -print comments test.res # print comment table
dune exec -- rescript -print ml test.res # show ocaml code
dune exec -- rescript -print res -width 80 test.res # test printer and change default print width

Benchmark:

make bench

Enable stack trace:

# Before you run the binary
export OCAMLRUNPARAM="b"

This is likely a known knowledge: add the above line into your shell rc file so that every shell startup you have OCaml stack trace enabled.

Development Docs

Folder Structure

  • src contains all the parser/printer source code. Don't change folder structure without notice; The rescript-compiler repo uses this repo as a submodule and assumes src.
  • benchmarks, cli and tests contain the source code for the executables used for testing/benchmarking. These are not used by the rescript-compiler repo.

Error Reporting Logic

Right now, ReScript's compiler's error reporting mechanism, for architectural reasons, is independent from this syntax repo's error reporting mechanism. However, we do want a unified look when they report the errors in the terminal. This is currently achieved by (carefully...) duplicating the error report logic from the compiler repo to here (or vice-versa; either way, just keep them in sync). The files to sync are the compiler repo's super_location.ml and super_code_frame.ml, into this repo's res_diagnostics_printing_utils.ml. A few notes:

  • Some lines are lightly changed to fit this repo's needs; they're documented in the latter file.
  • Please keep these files lightweight and as dependency-less as possible, for easier syncing.
  • The syntax logic currently doesn't have warnings, only errors, and potentially more than one.
  • In the future, ideally, the error reporting logic would also be unified with GenType and Reanalyze's. It'd be painful to copy paste around all this reporting logic.
  • The errors are reported by the parser here.
  • Our editor plugin parses the error report from the compiler and from the syntax here.

Example API usage

let filename = "foo.res"
let src = FS.readFile filename

let p =
  (* intended for ocaml compiler *)
  let mode = Res_parser.ParseForTypeChecker in
  (* if you want to target the printer use: let mode = Res_parser.Default in*)
  Res_parser.make ~mode src filename

let structure = Res_core.parseImplementation p
let signature = Res_core.parseSpecification p

let () = match p.diagnostics with
| [] -> () (* no problems *)
| diagnostics -> (* parser contains problems *)
  Res_diagnostics.printReport diagnostics src