Skip to content

Commit

Permalink
tweak: Fix README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
dhedey committed Dec 6, 2024
1 parent 55d6bd2 commit 6754b92
Showing 1 changed file with 25 additions and 32 deletions.
57 changes: 25 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,17 +358,17 @@ The idea is that we create two new tools:

In more detail:

* `[!parse! (<PARSE_DESTRUCTURING>) = (<INPUT>)]` is a more general `[!set!]` which acts like a `let <XX> = <YY> else { panic!() }`. It takes a `()`-wrapped parse destructuring on the left and a token stream as input on the right. Any `#x` in the parse definition acts as a binding rather than as a substitution. Parse operations look like `[<] Iterations are _not_ supported, but `[!optional] This will handled commas intelligently, and accept intelligent parse-helpers like:
* `[<fields> { hello: #a, world?: #b }]` - which can parse `#x` in any order, cope with trailing commas, and permit fields on the RHS not on the LHS
* `[<subfields> { hello: #a, world?: #b }]` - which can parse fields in any order, cope with trailing commas, and permit fields on the RHS not on the LHS
* `[<item> { #ident, #impl_generics, ... }]` - which calls syn's parse item on the token
* `[<ident> ...]`, `[<literal> ...]` and the like to parse idents / literals etc directly from the token stream (rather than token streams).
* More tailored examples, such as `[<generics> { impl: #x, type: #y, where: #z }]` which uses syn to parse the generics, and then uses subfields on the result.
* Possibly `[<group> #x]` to parse a group with no brackets, to avoid parser ambguity in some cases
* Any complex logic (loops, matching), is delayed lazily until execution logic time - making it much more intuitive.
* `[!for! (<PARSE_DESTRUCTURING>) in (<INPUT>) { ... }]` which operates like the rust `for` loop, and uses a parse destructuring on the left, and has support for optional commas between values
* `[!match! (<INPUT>) => { (<CASE1>) => { ... }, (<CASE2>) => { ... }, (#fallback) => { ... } }]` which operates like a rust `match` expression, and can replace the function of the branches of declarative macro inputs.
* `[!macro_rules! name!(<PARSE_DESTRUCTURING>) = { ... }]` which can define a declarative macro, but just parses its inputs as a token stream, and uses preinterpret for its heavy lifting.
* `[!parse! (DESTRUCTURING) = (INPUT)]` is a more general `[!set!]` which acts like a `let <XX> = <YY> else { panic!() }`. It takes a `()`-wrapped parse destructuring on the left and a token stream as input on the right. Any `#x` in the parse definition acts as a binding rather than as a substitution. Parsing will handled commas intelligently, and accept intelligent parse operations to do heavy-lifting for the user. Parse operations look like `[!OPERATION! DESTRUCTURING]` with the operation name in `UPPER_SNAKE_CASE`. Some examples might be:
* `[!FIELDS! { hello: #a, world?: #b }]` - which can be parsed in any order, cope with trailing commas, and forbid fields in the source stream which aren't in the destructuring.
* `[!SUBFIELDS! { hello: #a, world?: #b }]` - which can parse fields in any order, cope with trailing commas, and allow fields in the source stream which aren't in the destructuring.
* `[!ITEM! { #ident, #impl_generics, ... }]` - which calls syn's parse item on the token
* `[!IDENT! #x]`, `[!LITERAL! #x]`, `[!TYPE! { tokens: #x, path: #y }]` and the like to parse idents / literals etc directly from the token stream (rather than token streams). These will either take just a variable to capture the full token stream, or support an optional-argument style binding, where the developer can request certain sub-patterns or mapped token streams.
* More tailored examples, such as `[!GENERICS! { impl: #x, type: #y, where: #z }]` which uses syn to parse the generics, and then uses subfields on the result.
* Possibly `[!GROUPED! #x]` to parse a group with no brackets, to avoid parser ambiguity in some cases
* `[!OPTIONAL! ...]` might be supported, but other complex logic (loops, matching) is delayed lazily until interpretation time - which feels more intuitive.
* `[!for! (DESTRUCTURING) in (INPUT) { ... }]` which operates like the rust `for` loop, and uses a parse destructuring on the left, and has support for optional commas between values
* `[!match! (INPUT) => { (DESTRUCTURING_1) => { ... }, (DESTRUCTURING_2) => { ... }, (#fallback) => { ... } }]` which operates like a rust `match` expression, and can replace the function of the branches of declarative macro inputs.
* `[!macro_rules! name!(DESTRUCTURING) = { ... }]` which can define a declarative macro, but just parses its inputs as a token stream, and uses preinterpret for its heavy lifting.

And then we can end up with syntax like the following:

Expand All @@ -385,39 +385,32 @@ preinterpret::preinterpret! {
}]
}]
}
// Or can parse input - although loops are kept as a token stream and delegated
// to explicit lazy iteration, allowing a more procedural code style,
// and clearer compiler errors.
my_macro!(
MyTrait for MyType,
MyTrait for MyType2,
);
// It can also parse its input in the declaration.
// Repeated sections have to be captured as a stream, and delegated to explicit lazy [!for! ...] binding.
// This enforces a more procedural code style, and gives clearer compiler errors.
preinterpret::preinterpret! {
[!macro_rules! multi_impl_super_duper!(
#type_list,
ImplOptions [!fields! {
hello: #hello,
world?: #world (default "Default")
ImplOptions [!FIELDS! {
greeting: #hello,
location: #world,
punctuation?: #punct = ("!") // Default
}]
) = {
[!for! (
#type [!generics! { impl: #impl_generics, type: #type_generics }]
#type [!GENERICS! { impl: #impl_generics, type: #type_generics }]
) in (#type_list) {
impl<#impl_generics> SuperDuper for #type #type_generics {
type Hello = #hello;
type World = #world;
const Hello: &'static str = [!string! #hello " " #world #punct];
}
}]
}]
}
preinterpret::preinterpret! {
[!set! #input =
MyTrait for MyType,
MyTrait for MyType2,
]
[!for! (#trait for #type) in (#input) {
impl #trait for #type
}]
}
```

### Possible extension: Integer commands
Expand Down

0 comments on commit 6754b92

Please sign in to comment.