Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add to support include! for load partial for Pest grammars. #759

Closed
wants to merge 2 commits into from

Conversation

huacnlee
Copy link
Member

@huacnlee huacnlee commented Jan 4, 2023

Resolve #197 #333

Example

base.pest

WHITESPACE = _{ " " | "\t" | "\r" | "\n" }

json.pest

include!("base.pest")

json = { ... }

Will same as:

WHITESPACE = _{ " " | "\t" | "\r" | "\n" }

json = { ... }

@huacnlee huacnlee requested a review from a team as a code owner January 4, 2023 15:51
@huacnlee huacnlee requested review from tomtau and removed request for a team January 4, 2023 15:51
@huacnlee
Copy link
Member Author

huacnlee commented Jan 4, 2023

Or how about use:

A. Import

import("base.pest")

B. Require same as Node.js, Ruby

require("base.pest")

C. Rust include! macro.

include!("base.pest")

@huacnlee
Copy link
Member Author

huacnlee commented Jan 4, 2023

@CAD97 I have updated syntax to include!("base.pest") in last commit.

@huacnlee huacnlee force-pushed the feat/use-syntax branch 2 times, most recently from 26cf4ed to 58af2e9 Compare January 4, 2023 16:26
@huacnlee huacnlee changed the title Add to support use for load partial for Pest grammars. Add to support include! for load partial for Pest grammars. Jan 4, 2023
@tomtau tomtau requested review from CAD97, NoahTheDuke and a team January 5, 2023 01:16
Copy link
Contributor

@tomtau tomtau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged that original split PR, so this can be rebased on top of the latest master

base.pest

```pest
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
```

json.pest

```pest
use "base.pest"

json = { ... }
```

Will same as:

```pest
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }

json = { ... }
```
@huacnlee
Copy link
Member Author

huacnlee commented Jan 5, 2023

@tomtau I have updated

Copy link
Contributor

@tomtau tomtau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems all right. I don't have any special preference for the syntax: include may be fine, just that Rust-like syntax form may perhaps be confusing to lead people into thinking they can embed Rust code.

One thing that's missing is docs: when should one use this include statement versus using multiple derive expressions?

@huacnlee
Copy link
Member Author

huacnlee commented Jan 9, 2023

pest-parser/book#29

@tomtau
Copy link
Contributor

tomtau commented Jan 9, 2023

@huacnlee from those docs, if I understand it correctly, derive and this include meta extension achieve exactly the same outcome, i.e. there is no practical difference between them, or is there (e.g. if one of them doesn't work and the other one works in some workspace or old rustc/cargo settings?)?

huacnlee added a commit to huacnlee/pest-book that referenced this pull request Jan 9, 2023
@huacnlee
Copy link
Member Author

By my mind, include! just another way to let us to load partial grammars.

Because of this is same as the Rust include! macro, so it easier to understand.

In most sense, we just need focus on the .pest files (e.g. Share the .pest files to other project, we just need copy the files).

@huacnlee huacnlee requested review from tomtau and removed request for CAD97 and NoahTheDuke January 12, 2023 13:24
@tomtau tomtau requested a review from CAD97 January 13, 2023 00:55
Copy link
Contributor

@tomtau tomtau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm putting this one on hold for now, because it's not obvious what specific problem it solves (given multiple grammar file loading is already supported via derive generators #758) and whether it's worth extending the meta grammar with a feature that duplicates what is already possible using derive generators.

If someone from @pest-parser/maintainers @pest-parser/triage finds the extension useful in its current form and champions this PR, I think it's ok to go forward with it. Otherwise, it will be better to extend the meta grammar with a feature that is not achieved using derive generators, such as module-level scoping as sketched out in #660 .

Copy link
Contributor

@CAD97 CAD97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got no big concerns here. It's a simplistic form of code reuse, to be sure, but it's sufficient for simple cases and imo clear about its limitations.

Some minor impl nits and a few questions about semantics; I'll defer to @tomtau on what should block merge.

}

/// Get path relative to `path` dir, or relative to root path
fn partial_path(path: Option<&PathBuf>, filename: &str) -> PathBuf {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should take Option<&Path> instead. That might just work out at the call site, or it might require &* or .as_deref(), I'm not sure.

fn partial_path(path: Option<&PathBuf>, filename: &str) -> PathBuf {
let root = match path {
Some(path) => path.parent().unwrap().to_path_buf(),
None => join_path("./"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since join_path looks for the presence of a file to choose between the manifest dir or source dir, this is going to always use the src dir.

We should deliberately pick one as the "location" of attribute-inline grammars, or perhaps a better choice, just disallow include!.

Threading up an error from here might be a bigger change, unfortunately.

Comment on lines +66 to +70
// Add .pest suffix if not exist
let mut filename = filename.to_string();
if !filename.to_lowercase().ends_with(".pest") {
filename.push_str(".pest");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to create file extension less files, so adding an extension on automatically is probably not a great choice. If we do want to add an extension, it should be done via conversion to and then modification via PathBuf rather than string manipulation.

@@ -45,34 +81,16 @@ pub fn derive_parser(input: TokenStream, include_grammar: bool) -> TokenStream {

let mut data = String::new();
let mut path = None;
let mut has_use = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be has_include now.

Comment on lines +132 to +138
if has_use {
// Re-parse the data again, after replacing the `use` statement
pairs = match parser::parse(Rule::grammar_rules, &data) {
Ok(pairs) => pairs,
Err(error) => panic!("error parsing \n{}", error.renamed_rules(rename_meta_rule)),
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing it this way rather than in a loop means that only a single layer of include! will be resolved; a include! of a file with an include! won't work.

At a minimum we need a test for this case. Ideally we'd make it work, but so long as it results in an error rather than silently causing corruption it's not too bad.

@huacnlee
Copy link
Member Author

@tomtau Okey, I get it.

@tomtau
Copy link
Contributor

tomtau commented Jan 13, 2023

@huacnlee I think one potential use case may be in contexts where one cannot use Rust derive generators. For example:

  • the CLI debugger loads the grammar files directly;
  • the online fiddle editor doesn't even have a concept of a filesystem: https://pest.rs/#editor (but I can imagine it could perhaps be extended to have "multi-tab" editing where different grammar files are pasted into different text boxes)

So in the current form, it will also need to add support for include! in pest_vm and have some sample + test in pest_debugger

tomtau added a commit to pest-parser/book that referenced this pull request Jan 29, 2023
* Add doc for load multiple pest files and `include!` syntax.

Ref:

- pest-parser/pest#759
- pest-parser/pest#758

* Apply suggestions from code review

---------

Co-authored-by: Tomas Tauber <2410580+tomtau@users.noreply.github.com>
@huacnlee huacnlee closed this Feb 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sharing rules between grammars?
3 participants