Skip to content

Latest commit

 

History

History
246 lines (194 loc) · 10.7 KB

parser.md

File metadata and controls

246 lines (194 loc) · 10.7 KB

The Babel Parser

Example

See a simple example of how to use the parser at /src/parser/example.cjs.

Docs

The docs for the parser are at https://babeljs.io/docs/babel-parser

Article Creating custom JavaScript syntax with Babel

See the Svelte maintainer Tan Li Hau (陈立豪) article "Creating custom JavaScript syntax with Babel" (September 25, 2019) available at https://lihautan.com/creating-custom-javascript-syntax-with-babel where the author creates a curry function syntax @@:

// '@@' makes the function `foo` curried
function @@ foo(a, b, c) {
  return a + b + c;
}
console.log(foo(1, 2)(3)); // 6

the parser is a recursive descent parser.

See tan-liu-article.md for the summary of my experience reproducing Tan Liu Hau's article.

Babel Parser Plugins

See section /doc/parser/optional-chaining-in-the-parser.md

Parser Output: The Babel AST

The Babel AST specification is at file spec.md in repo https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md

The Babel parser generates AST according to Babel AST format. It is based on ESTree spec with the following deviations:

Producing a estree compatible AST with the babel parser

The example /src/parser/estree-example.js shows how to produce a estree compatible AST using the babel parser using the plugin estree:

➜ babel-learning git:(main) ✗ cat src/parser/estree-example.js

// This example shows how to produce a estree compatible AST using the babel parser.
const babel = require('@babel/core');
const source = '4';
const options = {
  parserOpts: {
    // https://babeljs.io/docs/en/babel-parser#options
    plugins: ['estree']
  }
};
const ast = babel.parseSync(source, options);
console.log(JSON.stringify(ast, function skip(key, value) {
  if (['loc', 'start', 'end', 'directives', 'comments'].includes(key)) {
    return undefined;
  }
  return value;
}, 2));
//const generate = require("@babel/generator").default;
//console.log(generate(ast).code); // throws an error
const recast = require('recast');
console.log(recast.print(ast).code); // '4;'

The parseSync method receives the source code and options babel.parseSync(code: string, options?: Object) and returns an AST. The options object is described at https://babeljs.io/docs/en/babel-parser#options. Referenced presets and plugins will be loaded such that optional syntax plugins are automatically enabled.

The execution shows that the type field is now Literal instead of NumericLiteral:

➜ babel-learning git:(main) ✗ ➜ node src/parser/estree-example.js

{
  "type": "File",
  "errors": [],
  "program": {
    "type": "Program",
    "sourceType": "module",
    "interpreter": null,
    "body": [
      {
        "type": "ExpressionStatement",
        "expression": {
          "type": "Literal",
          "value": 4,
          "raw": "4"
        }
      }
    ]
  }
}
4;

See Tan Li Hau youtube video [Q&A] Is there specs for babel AST?. Recorded in 2021.

AST for JSX code

AST for JSX code is based on Facebook JSX AST.

Error codes

Error codes are useful for handling the errors thrown by @babel/parser.

There are two error codes, code and reasonCode.

  • code
    • Rough classification of errors (e.g. BABEL_PARSER_SYNTAX_ERROR, BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED).
  • reasonCode
    • Detailed classification of errors (e.g. MissingSemicolon, VarRedeclaration).

See example at /src/parser/error-example.cjs:

const { parse } = require("@babel/parser");

const ast = parse(`a b`, { errorRecovery: true });

console.log(ast.errors[0].code); // BABEL_PARSER_SYNTAX_ERROR
console.log(ast.errors[0].reasonCode); // MissingSemicolon

Notice how some AST is still generated despite the syntax error:

{
  "type": "File",
  "errors": [
    {
      "code": "BABEL_PARSER_SYNTAX_ERROR",
      "reasonCode": "MissingSemicolon",
      "pos": 1
    }
  ],
  "program": {
    "type": "Program",
    "sourceType": "script",
    "interpreter": null,
    "body": [
      {
        "type": "ExpressionStatement",
        "expression": {
          "type": "Identifier",
          "name": "a"
        }
      },
      {
        "type": "ExpressionStatement",
        "expression": {
          "type": "Identifier",
          "name": "b"
        }
      }
    ]
  }

The Parser: Files and organization

See /doc/parser/organization.md.

Top Level and parseBlockBody

See /doc/parser/top-level.md.

tc39

Ecma International's TC39 is a group of JavaScript developers, implementers, and academics collaborating with the community to maintain and evolve the definition of JavaScript.

See tc39.md

You can see examples of how Babel is used to study new syntactic and semantic proposals in sections

Tokenizer

See section /doc/parser/tokenizer.md.

References

See section References.