rowan_peg_utils/
lib.rs

1use std::{cell::{Cell, RefCell}, mem::{forget, take}};
2
3use rowan::{GreenNode, GreenNodeBuilder, SyntaxKind};
4
5#[derive(Debug)]
6pub struct QuietGuard<'b, 'a>(&'b ParseState<'a>);
7
8impl<'b, 'a> std::ops::Deref for QuietGuard<'b, 'a> {
9    type Target = &'b ParseState<'a>;
10
11    fn deref(&self) -> &Self::Target {
12        &self.0
13    }
14}
15
16impl<'b, 'a> Drop for QuietGuard<'b, 'a> {
17    fn drop(&mut self) {
18        self.0.quiet.update(|n| n+1);
19    }
20}
21
22#[derive(Debug)]
23pub struct RuleGuard<'b, 'a> {
24    state: &'b ParseState<'a>,
25    len: usize,
26    quiet: u32,
27    kind: SyntaxKind,
28}
29
30impl<'b, 'a> RuleGuard<'b, 'a> {
31    fn end_set(&self) {
32        self.state.quiet.set(self.quiet);
33    }
34
35    pub fn accept_token(self, text: &'a str) {
36        self.end_set();
37        self.state.action(Action::Token(self.kind, text));
38        forget(self);
39    }
40
41    pub fn accept_none(self) {
42        self.end_set();
43        forget(self);
44    }
45
46    pub fn accept(self) {
47        self.end_set();
48        self.state.action(Action::Finish);
49        forget(self);
50    }
51}
52
53impl<'b, 'a> Drop for RuleGuard<'b, 'a> {
54    fn drop(&mut self) {
55        let RuleGuard { state, len, quiet, kind: _ } = *self;
56        state.actions.borrow_mut().truncate(len);
57        state.quiet.set(quiet);
58    }
59}
60
61#[derive(Debug, Clone)]
62pub enum Action<'a> {
63    Token(SyntaxKind, &'a str),
64    Start(SyntaxKind),
65    Finish,
66}
67
68#[derive(Debug, Default)]
69pub struct ParseState<'a> {
70    actions: RefCell<Vec<Action<'a>>>,
71    quiet: Cell<u32>,
72    builder: GreenNodeBuilder<'static>,
73}
74
75impl<'a> ParseState<'a> {
76    pub fn clear(&mut self) {
77        let mut actions = take(&mut self.actions);
78        actions.get_mut().clear();
79        *self = Self {
80            actions,
81            quiet: 0.into(),
82            ..Default::default()
83        }
84    }
85
86    pub fn action(&self, action: Action<'a>) {
87        if self.quiet.get() == 0 {
88            self.actions.borrow_mut().push(action);
89        }
90    }
91
92    pub fn quiet(&self) -> QuietGuard<'_, 'a> {
93        QuietGuard(self)
94    }
95
96    pub fn guard(&self, kind: impl Into<SyntaxKind>) -> RuleGuard<'_, 'a> {
97        let kind = kind.into();
98        let guard = self.guard_token(kind);
99        self.action(Action::Start(kind));
100        guard
101    }
102
103    pub fn guard_token(&self, kind: impl Into<SyntaxKind>) -> RuleGuard<'_, 'a> {
104        let len = self.actions.borrow().len();
105        RuleGuard { state: self, len, quiet: self.quiet.get(), kind: kind.into() }
106    }
107
108    pub fn guard_none(&self) -> RuleGuard<'_, 'a> {
109        let kind = SyntaxKind(0);
110        self.guard_token(kind)
111    }
112
113    pub fn finish(&mut self) -> GreenNode {
114        for action in self.actions.get_mut().drain(..) {
115            match action {
116                Action::Token(kind, text) => {
117                    if !text.is_empty() {
118                        self.builder.token(kind, text)
119                    }
120                }
121                Action::Start(kind) => self.builder.start_node(kind),
122                Action::Finish => self.builder.finish_node(),
123            }
124        }
125        take(&mut self.builder).finish()
126    }
127}
128
129pub mod support {
130    use rowan::{Language, NodeOrToken, SyntaxNode, SyntaxToken};
131
132    pub fn tokens<L>(node: &SyntaxNode<L>, kind: L::Kind) -> impl Iterator<
133        Item = SyntaxToken<L>
134    >
135    where L: Language
136    {
137       node.children_with_tokens()
138           .filter_map(NodeOrToken::into_token)
139           .filter(move |token| token.kind() == kind)
140    }
141}
142pub use support::tokens;
143
144/// Expand into a let-chain matching option chain
145///
146/// # Roughly de-sugar
147///
148/// - `foo.bar.baz` -> `let Some(baz) = value.foo().bar().baz()`
149/// - `foo.bar.baz as x` -> `let Some(x) = value.foo().bar().baz()`
150/// - `foo.bar { a, b.c }` -> `let Some(bar) = value.foo().bar()
151///   && let Some(a) = bar.a() && let Some(c) = bar.b().c()`
152///
153/// # Examples
154///
155/// ```ignore
156/// match_options! {match atom {
157///     l_paren as _ => {},
158///     l_brack as _ => {
159///         // ...
160///     },
161///     ident => ident.text(),
162///     string => {},
163///     matches if matches.text() == "<>" => {},
164///     matches => {},
165///     _ => unreachable!(),
166/// }}
167/// ```
168#[macro_export]
169macro_rules! match_options {
170    (@arms($expr:tt)
171        $($level1:ident).+ $(as $name1:tt)?
172        $({$(
173            $($level2:ident).+ $(as $name2:tt)?
174            $({$(
175                $($level3:ident).+ $(as $name3:tt)?
176                $({$(
177                    $($level4:ident).+ $(as $name4:tt)?
178                ),+ $(,)?})?
179            ),+ $(,)?})?
180        ),+ $(,)?})?
181        $(if $guard:expr)?
182        => $code:expr
183        $(, $($t:tt)*)?
184    ) => {
185        if let ::core::option::Option::Some(__level1) = $expr $(.$level1())+
186            $($(
187                && let ::core::option::Option::Some(__level2) = __level1 $(.$level2())+
188                $($(
189                    && let ::core::option::Option::Some(__level3) = __level2 $(.$level3())+
190                    $($(
191                        && let ::core::option::Option::Some($crate::match_options! { @last$(($name4))? $($level4)+ }) = __level3 $(.$level4())+
192                    )+)?
193                    && let $crate::match_options! { @last$(($name3))? $($level3)+ } = __level3
194                )+)?
195                && let $crate::match_options! { @last$(($name2))? $($level2)+ } = __level2
196            )+)?
197            && let $crate::match_options! { @last$(($name1))? $($level1)+ } = __level1
198            $(&& $guard)?
199        {
200            $code
201        } $(else {
202            $crate::match_options! {
203                @arms($expr) $($t)*
204            }
205        })?
206    };
207    (@last $i1:ident) => { $i1 };
208    (@last $i1:ident $i2:ident) => { $i2 };
209    (@last $i1:ident $i2:ident $i3:ident) => { $i3 };
210    (@last $i1:ident $i2:ident $i3:ident $i4:ident) => { $i4 };
211    (@last($renamed:pat) $($_:tt)*) => { $renamed };
212    (@arms($expr:tt)) => {};
213    (@arms($expr:tt) _ => $e:expr $(,)?) => {$e};
214
215    (match $expr:tt {$($t:tt)+}) => {{
216        #[allow(irrefutable_let_patterns)]
217        {
218            $crate::match_options! {
219                @arms($expr) $($t)*
220            }
221        }
222    }};
223
224    // partial completion branch
225    ($i:ident $expr:tt) => { $i $expr };
226    (match $expr:tt {}) => { match $expr };
227}
228
229#[test]
230#[allow(unused)]
231fn feature() {
232    struct Foo;
233    struct Bar;
234    struct Baz;
235    impl Foo { fn bar(&self) -> Bar { Bar } }
236    impl Bar { fn baz(&self) -> Option<Baz> { Some(Baz) } }
237    impl Baz { fn foo(&self) -> Option<Foo> { Some(Foo) } }
238    impl Baz { fn bar(&self) -> Option<Bar> { Some(Bar) } }
239    match_options!{match Foo {
240        bar.baz as m { foo as _, bar as _ } => {}
241    }};
242}