peggyjs / peggy

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

Refer to specific grammar rule #386

Closed barsdeveloper closed 1 year ago

barsdeveloper commented 1 year ago

Is it possible to have one single grammar and decide to parse a specific text using one rule of this grammar which is not the main one?

Let's say I have the following, very simple grammar, boolean is my start rule.

false = "false" { return false; }
true  = "true"  { return true; }
boolean = true / false

But sometimes I would like to access in the generated file, no only boolean but maybe I just need to parse false or true, is that possible? I mean to export them separately through cli.

Mingun commented 1 year ago

Yes, see the --allowed-start-rules CLI argument / allowedStartRules config / API parameter:

$ node .\bin\peggy.js --help
Usage: peggy [options] [input_file]

Arguments:
  input_file                       Grammar file to read.  Use "-" to read stdin. (default: "-")

Options:
  ...
  --allowed-start-rules <rules>    Comma-separated list of rules the generated parser will be allowed to start parsing from.  (Can be specified multiple times) (default: the first rule in the grammar)
  ...
  -S, --start-rule <rule>          When testing, use the given rule as the start rule.  If this rule is not in the allowed start rules, it will be added.
  ...
hildjj commented 1 year ago

Also of note: you can specify "*" for the allowed start rules, to allow any rule to be a starter.

I'm going to keep this open in order to make sure the CLI docs say that.

barsdeveloper commented 1 year ago

Alright, I've managed to see it with the cli, you need to specify startRule on options arg of the function parse. Can you please show me where to put the "*" for example on the false rule in the mini grammar on top?

hildjj commented 1 year ago
"use strict";

const peggy = require("./");

const  { parse } = peggy.generate(`
false = "false" { return false; }
true  = "true"  { return true; }
boolean = true / false`, {
  allowedStartRules: ["*"],
});

console.log(parse("true", { startRule: "boolean" }));
barsdeveloper commented 1 year ago

Understood, this is basically the equivalent of the CLI but when generating the grammar at runtime. I hoped there was some way to flag rules in the grammar itself to tell the generator (CLI or peggy.generate) what default starting rules to have.

Let's say I have mygrammar.peggy

*false = "false" { return false; }
true  = "true"  { return true; }
*boolean = true / false

And I want the starting rule to be either boolean or false. But as I understand this is not currently supported.

hildjj commented 1 year ago

You are correct there is currently no mechanism inside the grammar for this, although that's a good idea. When we do rule importing (see #292 for initial work), some rules might be marked as public and others as private, for instance. There are other bits of metadata that might be interesting about rules, such as anticipated types for Typescript output, enabling tracing per-rule, example inputs that get automatically tested, etc.

We could come up with something like ECMAscript/Typescript decorators, have a syntax for comments like JSdoc, or decide that all of this is too complicated for the benefits that might accrue.

In the meantime, just keep an array of the rules you want to be made visible whenver you would have generated a * prefix, and pass that in where the ['*'] is in my example.