Skip to content

Instantly share code, notes, and snippets.

@subfuzion
Last active March 6, 2021 12:56
Show Gist options
  • Save subfuzion/808f91bfdfb88c7d5ed7 to your computer and use it in GitHub Desktop.
Save subfuzion/808f91bfdfb88c7d5ed7 to your computer and use it in GitHub Desktop.
Tracing with peg.js

PEG.js is a simple parser generator for JavaScript that produces fast parsers with excellent error reporting. You can use it to process complex data or computer languages and build transformers, interpreters, compilers and other tools easily.

PEG.js offers tracing support to help analyze parser issues with a grammar. The feature is very helpful, but it's not available yet on the version that's published to npm, it's not well-advertised, and not well-documented. This gist explains how to take advantage of PEG.js tracing support.

When you generate your parser, make sure you supply the trace option set to true. If using gulp, do something like this:

var peg = require('gulp-peg');

var paths = {
  peg: ['src/**/*.pegjs'],
  dist: 'dist'
};

var pegOptions = {
  trace: true
};

gulp.task('peg', ['clean'], function() {
  return gulp.src(paths.peg)
    .pipe(peg(pegOptions))
    .pipe(gulp.dest(paths.dist));
});

When calling the parse function of your parser, provide an argument for your tracer object:

parser.parse(text, { tracer: { trace: function(evt) {
   ...
}}});

Trace events objects have the following properties:

{
  "type": " (rule.enter | rule.fail | rule.match) ",
  "rule": " (the name of the rule being evaluated) ",
  "location": {
    "start": {
      "offset": 0,
      "line": 1,
      "column": 1
    },
    "end": {
      "offset": 0,
      "line": 1,
      "column": 1
    }
  }
}

Want your tracer object to behave like an EventEmitter? Provide a tracer that emits events like this:

var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;
var parser = require('./path-to-parser');

function Tracer() {
  EventEmitter.prototype.call(this);
}

inherits(Tracer, EventEmitter);

// tracer instances need to implement a `trace` method for peg
Tracer.prototype.trace = function(evt) {
  this.emit('parse', evt);
};

var tracer = new Tracer();
tracer.on('parse', function(evt) {
  // do something cool with the parse event
});

parser.parse(text, { tracer: tracer });
@localhostdotdev
Copy link

in js you need peg.generate(grammar, { trace: true }) to get the tracer, also https://github.com/okaxaki/pegjs-backtrace is pretty nice to see the backtrace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment