peggyjs / peggy

Peggy: Parser generator for JavaScript
https://peggyjs.org/
MIT License
934 stars 65 forks source link

How can I use the visitor pattern? #333

Open moar55 opened 1 year ago

moar55 commented 1 year ago

If I understand correctly, implementing a visitor pattern when traversing the ast is now supported. Is there some example showing how to create the visitor functions and use them?

Mingun commented 1 year ago

The visitor pattern always was the way how the AST is processed in Peggy. I think, the best way to understand is to check the passes folder of this repository.

hildjj commented 1 year ago

I left this open in case we wanted to document the visitor API. I don't currently want to do that because I want to replace the AST and code generation bits. I'm still leaving this open for the moment in case that change doesn't end up working.

AndrewRayCode commented 1 year ago

I don't think the internal visitors file should be documented nor part of the public API. Implementing a visitor module is up to consumers of peggy, and it depends on what kind of AST your parser produces. Babel visitors, for example, have the concept of a "path", with lots of functionality like removing nodes, adding nodes, and skipping nodes, as part of visiting, all of which are up to the consumer to implement.

hildjj commented 1 year ago

I mostly agree with the above arguments about not documenting the visitor pattern. However, we do provide a plugin capability that is documented, and one of the most obvious things to do in a plugin is to visit the AST.

mikeaustin commented 1 year ago

When I started using Pegjs/Peggy, I too wasn't sure what the best approach to generate and traverse the AST was. It can be dead simple, this is what I've been doing lately for small projects – a simple evaluate function that invokes nodes by type. I think a short blurb in the documentation about how to write visitors would help get people started more quickly, if there isn't one already.

{
  const visitors = {
    AddExpression: ({ leftExpression, rightExpression }) => {
      return evaluate(leftExpression) + evaluate(rightExpression);
    },

    NumericLiteral: ({ value }) => {
      return value;
    }
  }

  function evaluate(node) {
    return visitors[node.type](node);
  }
}

Program
  = expression:Expression {
      return evaluate(expression);
    }

https://github.com/mikeaustin/kopi/blob/develop/packages/kopi/test/parser3/sample50.pegjs

I've been toying with writing an interactive article about how to write a programming language, using only Peggy (and markdown). At https://mike-austin.com/react-desktop, open the "Let's Build a Language.md" in the Files app. My language, Kopi uses Peggy which you can try in the Terminal app, or in the interactive markdown files such as "Learning Kopi.md"