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.into()));
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}