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
129#[macro_export]
154macro_rules! match_options {
155 (@arms($expr:tt)
156 $($level1:ident).+ $(as $name1:tt)?
157 $({$(
158 $($level2:ident).+ $(as $name2:tt)?
159 $({$(
160 $($level3:ident).+ $(as $name3:tt)?
161 $({$(
162 $($level4:ident).+ $(as $name4:tt)?
163 ),+ $(,)?})?
164 ),+ $(,)?})?
165 ),+ $(,)?})?
166 $(if $guard:expr)?
167 => $code:expr
168 $(, $($t:tt)*)?
169 ) => {
170 if let ::core::option::Option::Some(__level1) = $expr $(.$level1())+
171 $($(
172 && let ::core::option::Option::Some(__level2) = __level1 $(.$level2())+
173 $($(
174 && let ::core::option::Option::Some(__level3) = __level2 $(.$level3())+
175 $($(
176 && let ::core::option::Option::Some($crate::match_options! { @last$(($name4))? $($level4)+ }) = __level3 $(.$level4())+
177 )+)?
178 && let $crate::match_options! { @last$(($name3))? $($level3)+ } = __level3
179 )+)?
180 && let $crate::match_options! { @last$(($name2))? $($level2)+ } = __level2
181 )+)?
182 && let $crate::match_options! { @last$(($name1))? $($level1)+ } = __level1
183 $(&& $guard)?
184 {
185 $code
186 } $(else {
187 $crate::match_options! {
188 @arms($expr) $($t)*
189 }
190 })?
191 };
192 (@last $i1:ident) => { $i1 };
193 (@last $i1:ident $i2:ident) => { $i2 };
194 (@last $i1:ident $i2:ident $i3:ident) => { $i3 };
195 (@last $i1:ident $i2:ident $i3:ident $i4:ident) => { $i4 };
196 (@last($renamed:pat) $($_:tt)*) => { $renamed };
197 (@arms($expr:tt)) => {};
198 (@arms($expr:tt) _ => $e:expr $(,)?) => {$e};
199
200 (match $expr:tt {$($t:tt)+}) => {{
201 #[allow(irrefutable_let_patterns)]
202 {
203 $crate::match_options! {
204 @arms($expr) $($t)*
205 }
206 }
207 }};
208
209 ($i:ident $expr:tt) => { $i $expr };
211 (match $expr:tt {}) => { match $expr };
212}
213
214#[test]
215#[allow(unused)]
216fn feature() {
217 struct Foo;
218 struct Bar;
219 struct Baz;
220 impl Foo { fn bar(&self) -> Bar { Bar } }
221 impl Bar { fn baz(&self) -> Option<Baz> { Some(Baz) } }
222 impl Baz { fn foo(&self) -> Option<Foo> { Some(Foo) } }
223 impl Baz { fn bar(&self) -> Option<Bar> { Some(Bar) } }
224 match_options!{match Foo {
225 bar.baz as m { foo as _, bar as _ } => {}
226 }};
227}