diff options
-rw-r--r-- | src/drop_bomb.rs | 21 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/parser_api.rs | 41 |
3 files changed, 43 insertions, 20 deletions
diff --git a/src/drop_bomb.rs b/src/drop_bomb.rs new file mode 100644 index 000000000..750904a01 --- /dev/null +++ b/src/drop_bomb.rs | |||
@@ -0,0 +1,21 @@ | |||
1 | use std::borrow::Cow; | ||
2 | |||
3 | pub struct DropBomb { | ||
4 | msg: Cow<'static, str>, | ||
5 | defused: bool, | ||
6 | } | ||
7 | |||
8 | impl DropBomb { | ||
9 | pub fn new(msg: impl Into<Cow<'static, str>>) -> DropBomb { | ||
10 | DropBomb { msg: msg.into(), defused: false } | ||
11 | } | ||
12 | pub fn defuse(&mut self) { self.defused = true } | ||
13 | } | ||
14 | |||
15 | impl Drop for DropBomb { | ||
16 | fn drop(&mut self) { | ||
17 | if !self.defused && !::std::thread::panicking() { | ||
18 | panic!("{}", self.msg) | ||
19 | } | ||
20 | } | ||
21 | } | ||
diff --git a/src/lib.rs b/src/lib.rs index 1cd45690a..d9572912c 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
@@ -31,6 +31,7 @@ mod lexer; | |||
31 | mod parser_api; | 31 | mod parser_api; |
32 | mod grammar; | 32 | mod grammar; |
33 | mod parser_impl; | 33 | mod parser_impl; |
34 | mod drop_bomb; | ||
34 | 35 | ||
35 | mod syntax_kinds; | 36 | mod syntax_kinds; |
36 | /// Utilities for simple uses of the parser. | 37 | /// Utilities for simple uses of the parser. |
diff --git a/src/parser_api.rs b/src/parser_api.rs index d12f773b2..3cad91976 100644 --- a/src/parser_api.rs +++ b/src/parser_api.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use { | 1 | use { |
2 | parser_impl::ParserImpl, | 2 | parser_impl::ParserImpl, |
3 | SyntaxKind::{self, ERROR}, | 3 | SyntaxKind::{self, ERROR}, |
4 | drop_bomb::DropBomb, | ||
4 | }; | 5 | }; |
5 | 6 | ||
6 | #[derive(Clone, Copy)] | 7 | #[derive(Clone, Copy)] |
@@ -76,7 +77,7 @@ impl<'t> Parser<'t> { | |||
76 | /// consumed between the `start` and the corresponding `Marker::complete` | 77 | /// consumed between the `start` and the corresponding `Marker::complete` |
77 | /// belong to the same node. | 78 | /// belong to the same node. |
78 | pub(crate) fn start(&mut self) -> Marker { | 79 | pub(crate) fn start(&mut self) -> Marker { |
79 | Marker(self.0.start()) | 80 | Marker::new(self.0.start()) |
80 | } | 81 | } |
81 | 82 | ||
82 | /// Advances the parser by one token. | 83 | /// Advances the parser by one token. |
@@ -131,31 +132,31 @@ impl<'t> Parser<'t> { | |||
131 | } | 132 | } |
132 | 133 | ||
133 | /// See `Parser::start`. | 134 | /// See `Parser::start`. |
134 | pub(crate) struct Marker(u32); | 135 | pub(crate) struct Marker { |
136 | pos: u32, | ||
137 | bomb: DropBomb, | ||
138 | } | ||
135 | 139 | ||
136 | impl Marker { | 140 | impl Marker { |
141 | fn new(pos: u32) -> Marker { | ||
142 | Marker { | ||
143 | pos, | ||
144 | bomb: DropBomb::new("Marker must be either completed or abandoned") | ||
145 | } | ||
146 | } | ||
147 | |||
137 | /// Finishes the syntax tree node and assigns `kind` to it. | 148 | /// Finishes the syntax tree node and assigns `kind` to it. |
138 | pub(crate) fn complete(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { | 149 | pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { |
139 | let pos = self.0; | 150 | self.bomb.defuse(); |
140 | ::std::mem::forget(self); | 151 | p.0.complete(self.pos, kind); |
141 | p.0.complete(pos, kind); | 152 | CompletedMarker(self.pos) |
142 | CompletedMarker(pos) | ||
143 | } | 153 | } |
144 | 154 | ||
145 | /// Abandons the syntax tree node. All its children | 155 | /// Abandons the syntax tree node. All its children |
146 | /// are attached to its parent instead. | 156 | /// are attached to its parent instead. |
147 | pub(crate) fn abandon(self, p: &mut Parser) { | 157 | pub(crate) fn abandon(mut self, p: &mut Parser) { |
148 | let pos = self.0; | 158 | self.bomb.defuse(); |
149 | ::std::mem::forget(self); | 159 | p.0.abandon(self.pos); |
150 | p.0.abandon(pos); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | impl Drop for Marker { | ||
155 | fn drop(&mut self) { | ||
156 | if !::std::thread::panicking() { | ||
157 | panic!("Marker must be either completed or abandoned"); | ||
158 | } | ||
159 | } | 160 | } |
160 | } | 161 | } |
161 | 162 | ||
@@ -170,6 +171,6 @@ impl CompletedMarker { | |||
170 | /// `B` before starting `A`. `precede` allows to do exactly | 171 | /// `B` before starting `A`. `precede` allows to do exactly |
171 | /// that. See also docs about `forward_parent` in `Event::Start`. | 172 | /// that. See also docs about `forward_parent` in `Event::Start`. |
172 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | 173 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { |
173 | Marker(p.0.precede(self.0)) | 174 | Marker::new(p.0.precede(self.0)) |
174 | } | 175 | } |
175 | } | 176 | } |