Syntax Delegate

The last argument in the parseScript/parseModule function is a delegate, a callback function invoked for each syntax node (as the node is constructed) with two arguments, the node object itself and the node metadata. The metadata contains the start and end location of the node.

The shortest Node.js script that illustrates the delegate is the following:

  1. var esprima = require('esprima');
  2. esprima.parseScript('answer = 42', {}, function (node) {
  3. console.log(node.type);
  4. });

If the script is called delegate.js, running it with Node.js gives the output:

  1. $ node delegate.js
  2. Identifier
  3. Literal
  4. AssignmentExpression
  5. ExpressionStatement
  6. Program

In the above example, the callback function only does one simple thing: printing the type of the node. The first two calls are with the deepest nodes (which are also leaves), an Identifier node representing answer and a Literal node for 42. The next is with an AssignmentExpression node that combines the previous two nodes (answer = 42). It is then followed by the only statement in the code fragment, an ExpressionStatement node. The last one, as with every syntax tree, is always the top-level Program node.

The order of the nodes being passed as the argument for the callback function resembles a tree traversal using the depth-first algorithm.

If each single-line and multi-line comment must be passed to the callback function as well, the comment flag in the parsing configuration needs to be true. A modified delegate.js and its new result (note the addition of LineComment node type):

  1. $ cat delegate.js
  2. var esprima = require('esprima');
  3. esprima.parseScript('answer = 42 // FIXME', { comment: true }, function (node) {
  4. console.log(node.type);
  5. });
  6.  
  7. $ node delegate.js
  8. Identifier
  9. LineComment
  10. Literal
  11. AssignmentExpression
  12. ExpressionStatement
  13. Program

The second argument passed to the callback function, the metadata, can be used to locate the node. It is illustrated in the following example:

  1. $ cat delegate.js
  2. var esprima = require('esprima');
  3. esprima.parseScript('answer = 42', {}, function (node, metadata) {
  4. console.log(node.type, metadata);
  5. });
  6.  
  7. $ node delegate.js
  8. Identifier { start: { line: 1, column: 0, offset: 0 },
  9. end: { line: 1, column: 6, offset: 6 } }
  10. Literal { start: { line: 1, column: 9, offset: 9 },
  11. end: { line: 1, column: 11, offset: 11 } }
  12. AssignmentExpression { start: { line: 1, column: 0, offset: 0 },
  13. end: { line: 1, column: 11, offset: 11 } }
  14. ExpressionStatement { start: { line: 1, column: 0, offset: 0 },
  15. end: { line: 1, column: 11, offset: 11 } }
  16. Program { start: { line: 1, column: 0, offset: 0 },
  17. end: { line: 1, column: 11, offset: 11 } }