Skip to content

Commit

Permalink
Add support for the Meriyah parser
Browse files Browse the repository at this point in the history
Meriyah is a fast and modern implementation of ECMAScript parser
  • Loading branch information
prantlf committed May 7, 2022
1 parent 74feafb commit e0500d1
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ const tsAst = recast.parse(source, {
});
```

**Note:** Some of these parsers import npm packages that Recast does not directly depend upon, so please be aware you may have to run `npm install babylon@next` to use the `typescript`, `flow`, or `babylon` parsers, or `npm install acorn` to use the `acorn` parser. Only Esprima is installed by default when Recast is installed.
**Note:** Some of these parsers import npm packages that Recast does not directly depend upon, so please be aware you may have to run `npm install babylon@next` to use the `typescript`, `flow`, or `babylon` parsers, or `npm install acorn` to use the `acorn` parser, or `npm install meriyah` to use the `meriyah` parser. Only Esprima is installed by default when Recast is installed.

After calling `recast.parse`, if you're going to transform the AST, make sure that the `.original` property is preserved. With Babel, for instance, if you call `transformFromAST`, you must pass `cloneInputAst: false` in its options. ([More detail](https://github.com/babel/babel/issues/12882).

Expand Down
4 changes: 2 additions & 2 deletions lib/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export function parse(source: string, options?: Partial<Options>) {
program = ast;
// In order to ensure we reprint leading and trailing program
// comments, wrap the original Program node with a File node. Only
// ESTree parsers (Acorn and Esprima) return a Program as the root AST
// node. Most other (Babylon-like) parsers return a File.
// ESTree parsers (Acorn, Esprima, Meriyah) return a Program as the root
// AST node. Most other (Babylon-like) parsers return a File.
file = b.file(ast, options.sourceFileName || null);
file.loc = {
start: lines.firstPos(),
Expand Down
16 changes: 16 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"flow-parser": "0.156.0",
"glob": "7.2.0",
"lint-staged": "^12.4.1",
"meriyah": "^4.2.1",
"mocha": "9.0.2",
"prettier": "^2.6.2",
"reify": "0.20.12",
Expand Down
36 changes: 36 additions & 0 deletions parsers/meriyah.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This module is suitable for passing as options.parser when calling
// recast.parse to process JavaScript code with Meriyah:
//
// const ast = recast.parse(source, {
// parser: require("recast/parsers/meriyah")
// });
//
import { getOption } from "../lib/util";

function convertComment(comment: any): any {
let { type } = comment;
type = type[0] === 'S' ? 'Line' : 'Block'; // SingleLine/MultiLine
return { ...comment, type };
}

export function parse(source: string, options?: any) {
const comments: any[] = [];
const tokens: any[] = [];
const ast = require("meriyah").parse(source, {
module: getOption(options, "sourceType", "module") === "module",
specDeviation: getOption(options, "tolerant", true),
jsx: getOption(options, "jsx", false),
ranges: getOption(options, "range", false),
loc: true,
raw: true,
next: true,
globalReturn: true,
onComment: comments,
onToken: tokens,
});

ast.comments = comments.map(convertComment);
ast.tokens = tokens;

return ast;
}
2 changes: 2 additions & 0 deletions test/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const nodeMajorVersion = parseInt(process.versions.node, 10);
describe("comments", function () {
[
"../parsers/acorn",
"../parsers/meriyah",
"../parsers/babel",
"../parsers/esprima",
"../parsers/flow",
Expand Down Expand Up @@ -180,6 +181,7 @@ function runTestsForParser(parserId: any) {
const info = (
{
acorn: esprimaInfo,
meriyah: esprimaInfo,
babel: babelInfo,
esprima: esprimaInfo,
flow: babelInfo,
Expand Down
2 changes: 2 additions & 0 deletions test/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const nodeMajorVersion = parseInt(process.versions.node, 10);
describe("parser", function () {
[
"../parsers/acorn",
"../parsers/meriyah",
"../parsers/babel",
"../parsers/esprima",
"../parsers/flow",
Expand Down Expand Up @@ -84,6 +85,7 @@ function runTestsForParser(parserId: string) {

const lineCommentTypes: { [name: string]: string } = {
acorn: "Line",
meriyah: "Line",
babel: "CommentLine",
esprima: "Line",
flow: "CommentLine",
Expand Down
1 change: 1 addition & 0 deletions test/printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,7 @@ describe("printer", function () {

checkWith(require("../parsers/esprima"));
checkWith(require("../parsers/acorn"));
checkWith(require("../parsers/meriyah"));

if (nodeMajorVersion >= 6) {
checkWith(require("../parsers/babel"));
Expand Down

0 comments on commit e0500d1

Please sign in to comment.