FastParse is a Scala parser library that expects you to extend it
Writing Fast Parsers Fast in Scala
At a glance
- What is it?
- FastParse is a MIT licensed parser combinator library for Scala, cross built for the JVM and Scala.js, where three complete language parsers for Scala, Python and CSS sit in the same repository and act as the test suite. The contributor guide says plainly that the library is designed to be extended in your own code, and that changes can be reverted later.
- Who is it for?
- FastParse suits a Scala team that has to parse a language or a structured format, wants the parser to be an ordinary value that can be composed and tested, and is prepared to read the documentation site rather than a README. It is the wrong choice for a project that needs one small format parsed, since a hand written recursive descent parser would be less machinery and no dependency.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 64 days ago.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The README is developer documentation, not a tutorial
The first thing the README does is point you elsewhere. It says this is where the code for the FastParse parsing library lives, and that if you want to use FastParse you probably want the documentation, hosted at com-lihaoyi.github.io/fastparse. What follows in the README is explicitly framed as developer docs for people working on the repository rather than using it as a library.
That is worth noticing, because a parser library is judged on its API and its errors, and neither is described here. The README instead points at three external resources for understanding the design and the usage. There is a hands-on tutorial blog post on parsing with parser combinators for the basics, a post giving an overview of the design of FastParse 2, and the author's book, Hands-on Scala, which uses the library extensively, with an entire chapter on parsing structured text and a following chapter on implementing a programming language that makes heavy use of it.
The name of the project, Writing Fast Parsers Fast in Scala, sets the expectation, and the composition of the repository is what makes it credible. Three real parsers for real languages live in the same tree, and they are not examples, they are the test harness.
For licensing, it is MIT, copyright 2014 Li Haoyi, with the standard permission text in full in the README.
One core shared between the JVM and Scala.js
The core of FastParse lives in the fastparse/ folder, and it is a cross-built ScalaJVM and Scala.js codebase. Almost everything is shared between the two platforms in fastparse/src/, with minor differences in fastparse/src-js/ and fastparse/src-jvm/.
That layout is a deliberate statement about where the library's complexity is allowed to live. A parser combinator library has a natural temptation to grow platform specific machinery, and this one keeps the divergence down to two small directories. It also means the same parser source can be compiled to a browser, which is what the documentation site's live demos rely on.
The build has both a Mill build file, build.mill, and a Mill wrapper checked into the repository, alongside a build.sbt and a project/ directory for the sbt path, so the project supports both build tools. The README notes that you should use mill 0.11 or later.
For a library user this is mostly invisible. For someone reading the source, the split tells you where to look when behaviour differs between the JVM and the browser, and the two directories are the only place such differences are allowed to accumulate.
The language parsers are the real test suite
Three subprojects sit beside the core. scalaparse/, pythonparse/ and cssparse/ are FastParse parsers for those languages respectively, and the README says they are both usable as standalone libraries and serve as extensive test suites and use cases for FastParse itself.
The part that makes this more than a convenience is the next sentence: each of those projects clones and parses large quantities of code from GitHub as part of its own test suite. So the acceptance criterion for a change to the library is that it still parses a large body of real Scala, Python and CSS, not that a hand written example still returns the right answer. That is a much harder test to pass, and it explains why the library can claim coverage of full languages while sitting in one repository.
It also tells you how to use the project as a consumer. If you need a Scala parser, scalaparse is a FastParse parser for Scala and can be used on its own. If your problem is parsing CSS or Python, there is a parser for that too, built the same way.
The perftests/ directory holds performance tests for the main projects in the library, including ScalaParse, PythonParse and CssParse, which is where a change that trades correctness for speed would show up.
Running the suites, one Scala version at a time
The build commands are the practical part of working on the library, and the README is unusually clear about which one to use.
The main test suite runs like this:
mill -w "fastparse.jvm[2.12.10].test"The -w flag watches for changes, which is what you want while hacking on FastParse. The other suites, such as fastparse.js, scalaparse.jvm and the rest, are available in the same form, and the author says he typically does not run them by hand and leaves that to CI unless he is actively working on that sub-project.
Running the same suite against different Scala versions is a matter of changing the version in the brackets:
mill -w "fastparse.jvm[_].test"And the aggregate command runs everything, at a cost:
mill __.test.testThe README notes this is pretty slow, and offers a faster compromise that still catches most issues:
mill "__.jvm[2.12.17].test"The documentation site is built separately, and it is where the live demos come from, since readme/ contains the documentation site with several live demos of FastParse parsers compiled to Scala.js. The build command combines Mill and sbt:
mill demo.fullOpt && sbt readme/runThe result ends up at readme/target/scalatex/index.html, which tells you the site is generated with Scala.js and scalatex.
The contribution guide says the design is extensible on purpose
The contribution guidelines contain the clearest statement of the project's philosophy, and it is unusual to find it written this plainly.
The key line is that, to a large extent, FastParse is designed so that you can extend it in your own code without needing to modify the core. If you want to add features, you are told to be prepared to argue why it should be built in rather than just part of your own code. That is a design decision about where the library ends: the core stays small and the extension points are meant to be used from outside.
The same guide warns that it is entirely possible your changes will not be merged or will be ripped out later, and that this applies to the author's own changes. It also says a rejected or reverted pull request is still valuable, since it explores the solution space, and that for every line in the repository at least three lines were tried, committed and reverted, and more than ten were tried without committing. Proof-of-concept pull requests are explicitly welcome even when they are not meant to be merged.
The process rules follow from that. If you are not sure whether something is a bug, ask on Gitter first. All code pull requests should come with a meaningful description, inline comments for important things, unit tests and a green build. Non-trivial changes, including bug fixes, should appear in the changelog, and new features should be added to the relevant parts of the documentation.
Compatibility claims need reading twice
The final contribution bullet contains two statements that sit next to each other and pull in different directions. The first is that no binary or source compatibility is guaranteed between any releases. The second is that FastParse keeps compatibility following the SemVer rule, that upgrading is usually trivial, and that the author does not expect existing functionality to go away.
Read as a whole, the sensible interpretation is that the SemVer promise is about behaviour rather than about the shape of the published artefacts. A dependency that is compiled against one version and run against another may not link, but the parser semantics are expected to stay put. If you are a library consumer, that distinction matters only if you shade or compile FastParse into a shared artefact and expect it to be binary compatible across versions.
The maintenance picture matches that reading. The repository is not archived and the last push was on 2026-08-20, so work is still landing on the master branch. The published releases are much older: 2.3.3 from 2021-09-07, whose release note refers to fixing a cssparse bug when a comment is at the end of a block, and 2.1.2 from April 2019. A consumer pinning the newest release is pinning a five year old artefact, while the repository itself has moved on, and the gap between those two facts is the practical upgrade risk.
Because the project also depends on Mill and sbt and on a range of Scala versions, the dependency tree of a consumer is part of the upgrade cost, and the compatible artifact set for a given Scala version is something you confirm in the documentation rather than assume.
Editorial conclusion
FastParse suits a Scala team that has to parse a language or a structured format, wants the parser to be an ordinary value that can be composed and tested, and is prepared to read the documentation site rather than a README. It is the wrong choice for a project that needs one small format parsed, since a hand written recursive descent parser would be less machinery and no dependency. Verify first which released version you want to depend on, because the newest published release is 2.3.3 from 2021-09-07 while the repository itself was pushed on 2026-08-20, and the contribution guide states that no binary or source compatibility is guaranteed between releases even though the project follows SemVer.
Frequently asked questions
What is FastParse?
It is a MIT licensed parsing library for Scala, described as writing fast parsers fast in Scala, cross built for the JVM and Scala.js. The core lives in the fastparse/ folder, with almost everything shared between the two platforms.
Which parsers are included in the FastParse repository?
Three subprojects: scalaparse/, pythonparse/ and cssparse/. Each is a FastParse parser for that language, usable as a standalone library, and each clones and parses large quantities of real code from GitHub as part of its own test suite.
How do I run the FastParse test suite?
With mill -w "fastparse.jvm[2.12.10].test" for the main suite in watch mode, using mill 0.11 or later. The aggregate command is mill __.test.test, which the README notes is slow, and mill "__.jvm[2.12.17].test" is a faster compromise.
Can I add features to FastParse without modifying the core?
Yes, that is the stated design intent. The contribution guide says FastParse is designed so that you can extend it in your own code without needing to modify the core, and asks contributors proposing built-in features to argue why it should not just live in their own code.
Is FastParse binary compatible across releases?
The contribution guide states that no binary or source compatibility is guaranteed between any releases, while also saying the project follows the SemVer rule, that upgrading is usually trivial and that existing functionality is not expected to go away.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/com-lihaoyi-fastparse)Was this useful?