Skip to content

Commit b88a9b9

Browse files
committed
v0.9.5
1 parent b815f7e commit b88a9b9

File tree

6 files changed

+53
-10
lines changed

6 files changed

+53
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org).
88
Note: In this file, do not use the hard wrap in the middle of a sentence for compatibility with GitHub comment style markdown rendering.
99
-->
1010

11+
## [0.9.5] - 2025-07-02
12+
13+
- Derive: syntax add `try_filter` attribute.
14+
1115
## [0.9.4] - 2025-07-02
1216

1317
- ErrorKind: add impl `ToSpan`.

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2024"
55
license = "MIT"
66
name = "parserc"
77
repository = "https://github.com/styles-lab/parserc"
8-
version = "0.9.3"
8+
version = "0.9.5"
99

1010
[dependencies]
1111
memchr = "^2.7"

core/src/errors.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,20 @@ impl<T, I, E> MapFatal for Result<T, I, E> {
7070
}
7171

7272
/// An extension trait for `std::result::Result<(T, I), ControlFlow<E>>`
73-
pub trait MapError<E1, E2> {
73+
pub trait MapError<E> {
7474
type Output;
7575
/// map underlying `ControlFlow`
7676
fn map_control_flow_err<F>(self, f: F) -> Self::Output
7777
where
78-
F: FnOnce(E1) -> E2;
78+
F: FnOnce(E) -> E;
7979
}
8080

81-
impl<T, I, E1, E2> MapError<E1, E2> for Result<T, I, E1> {
82-
type Output = Result<T, I, E2>;
81+
impl<T, I, E> MapError<E> for Result<T, I, E> {
82+
type Output = Result<T, I, E>;
8383

8484
fn map_control_flow_err<F>(self, f: F) -> Self::Output
8585
where
86-
F: FnOnce(E1) -> E2,
86+
F: FnOnce(E) -> E,
8787
{
8888
match self {
8989
Err(ControlFlow::Fatal(err)) => Err(ControlFlow::Fatal(f(err))),
@@ -116,3 +116,23 @@ impl<T1, T2, I, E> Map<T1, T2> for Result<T1, I, E> {
116116
}
117117
}
118118
}
119+
120+
/// An extension trait for `std::result::Result<(T, I), ControlFlow<E>>`
121+
pub trait TryFilter<T, I, E> {
122+
/// map underlying `ControlFlow`
123+
fn try_filter_control_flow<F>(self, f: F) -> Result<T, I, E>
124+
where
125+
F: FnOnce(T) -> std::result::Result<T, ControlFlow<E>>;
126+
}
127+
128+
impl<T, I, E> TryFilter<T, I, E> for Result<T, I, E> {
129+
fn try_filter_control_flow<F>(self, f: F) -> Result<T, I, E>
130+
where
131+
F: FnOnce(T) -> std::result::Result<T, ControlFlow<E>>,
132+
{
133+
match self {
134+
Ok((t, i)) => f(t).map(|t| (t, i)),
135+
Err(err) => Err(err),
136+
}
137+
}
138+
}

derive/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2024"
55
license = "MIT"
66
name = "parserc-derive"
77
repository = "https://github.com/styles-lab/parserc"
8-
version = "0.9.3"
8+
version = "0.9.5"
99

1010
[dependencies]
1111
proc-macro2 = "^1"

derive/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub fn tokens(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
1818
}
1919

2020
/// Derive `Syntax` trait for `structs/enums`.
21-
#[proc_macro_derive(Syntax, attributes(syntax, fatal, from, map_err))]
21+
#[proc_macro_derive(Syntax, attributes(syntax, fatal, from, map_err, try_filter))]
2222
pub fn derive_syntax_trait(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2323
syntax::derive_syntax_trait(input)
2424
}

derive/src/syntax.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ struct Field {
109109
ident: Ident,
110110
from_ty: Option<Type>,
111111
map_err: Option<Expr>,
112+
try_filter: Option<Expr>,
112113
fatal: bool,
113114
}
114115

@@ -120,6 +121,7 @@ impl TryFrom<(usize, &syn::Field)> for Field {
120121
let mut fatal = false;
121122
let mut from_ty = None;
122123
let mut map_err_fn = None;
124+
let mut try_filter = None;
123125

124126
for attr in &field.attrs {
125127
let path = attr.path();
@@ -130,6 +132,9 @@ impl TryFrom<(usize, &syn::Field)> for Field {
130132
} else if path.is_ident("map_err") {
131133
let expr: Expr = attr.parse_args()?;
132134
map_err_fn = Some(expr);
135+
} else if path.is_ident("try_filter") {
136+
let expr: Expr = attr.parse_args()?;
137+
try_filter = Some(expr);
133138
} else if path.is_ident("fatal") {
134139
fatal = true;
135140
}
@@ -140,12 +145,14 @@ impl TryFrom<(usize, &syn::Field)> for Field {
140145
ident: ident.clone(),
141146
from_ty,
142147
map_err: map_err_fn,
148+
try_filter,
143149
fatal,
144150
}),
145151
None => Ok(Self {
146152
ident: format_ident!("v_{}", index),
147153
from_ty,
148154
map_err: map_err_fn,
155+
try_filter,
149156
fatal,
150157
}),
151158
}
@@ -192,8 +199,13 @@ fn derive_syntax_for_enum(item: &ItemEnum) -> Result<proc_macro::TokenStream> {
192199
.as_ref()
193200
.map(|expr| quote! { .map_control_flow_err(#expr) });
194201

202+
let try_filter = field
203+
.try_filter
204+
.as_ref()
205+
.map(|expr| quote! { .try_filter_control_flow(#expr) });
206+
195207
quote! {
196-
let (#ident,input) = input.parse() #from_ty #map_err #fatal ?;
208+
let (#ident,input) = input.parse() #from_ty #map_err #try_filter #fatal ?;
197209
}
198210
});
199211

@@ -244,6 +256,7 @@ fn derive_syntax_for_enum(item: &ItemEnum) -> Result<proc_macro::TokenStream> {
244256
fn parse(input: #ty_input) -> parserc::errors::Result<Self, #ty_input, #ty_error> {
245257
use parserc::parser::Parser;
246258
use parserc::errors::Map as _;
259+
use parserc::errors::TryFilter as _;
247260
use parserc::errors::MapFatal as _;
248261
use parserc::errors::MapError as _;
249262

@@ -294,8 +307,13 @@ fn derive_syntax_for_struct(item: &ItemStruct) -> Result<proc_macro::TokenStream
294307
.as_ref()
295308
.map(|expr| quote! { .map_control_flow_err(#expr) });
296309

310+
let try_filter = field
311+
.try_filter
312+
.as_ref()
313+
.map(|expr| quote! { .try_filter_control_flow(#expr) });
314+
297315
quote! {
298-
let (#ident,input) = input.parse() #from_ty #map_err #fatal ?;
316+
let (#ident,input) = input.parse() #from_ty #map_err #try_filter #fatal ?;
299317
}
300318
});
301319

@@ -321,6 +339,7 @@ fn derive_syntax_for_struct(item: &ItemStruct) -> Result<proc_macro::TokenStream
321339
fn parse(input: #ty_input) -> parserc::errors::Result<Self, #ty_input, #ty_error> {
322340
use parserc::parser::Parser;
323341
use parserc::errors::Map as _;
342+
use parserc::errors::TryFilter as _;
324343
use parserc::errors::MapFatal as _;
325344
use parserc::errors::MapError as _;
326345

0 commit comments

Comments
 (0)