aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/parsing/parser_api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/parsing/parser_api.rs')
-rw-r--r--crates/ra_syntax/src/parsing/parser_api.rs195
1 files changed, 195 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/parsing/parser_api.rs b/crates/ra_syntax/src/parsing/parser_api.rs
new file mode 100644
index 000000000..781c407de
--- /dev/null
+++ b/crates/ra_syntax/src/parsing/parser_api.rs
@@ -0,0 +1,195 @@
1use drop_bomb::DropBomb;
2
3use crate::{
4 SyntaxKind::{self, ERROR},
5 parsing::{
6 token_set::TokenSet,
7 parser_impl::ParserImpl
8 },
9};
10
11/// `Parser` struct provides the low-level API for
12/// navigating through the stream of tokens and
13/// constructing the parse tree. The actual parsing
14/// happens in the `grammar` module.
15///
16/// However, the result of this `Parser` is not a real
17/// tree, but rather a flat stream of events of the form
18/// "start expression, consume number literal,
19/// finish expression". See `Event` docs for more.
20pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>);
21
22impl<'t> Parser<'t> {
23 /// Returns the kind of the current token.
24 /// If parser has already reached the end of input,
25 /// the special `EOF` kind is returned.
26 pub(crate) fn current(&self) -> SyntaxKind {
27 self.nth(0)
28 }
29
30 /// Returns the kinds of the current two tokens, if they are not separated
31 /// by trivia.
32 ///
33 /// Useful for parsing things like `>>`.
34 pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
35 self.0.current2()
36 }
37
38 /// Returns the kinds of the current three tokens, if they are not separated
39 /// by trivia.
40 ///
41 /// Useful for parsing things like `=>>`.
42 pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
43 self.0.current3()
44 }
45
46 /// Lookahead operation: returns the kind of the next nth
47 /// token.
48 pub(crate) fn nth(&self, n: u32) -> SyntaxKind {
49 self.0.nth(n)
50 }
51
52 /// Checks if the current token is `kind`.
53 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
54 self.current() == kind
55 }
56
57 /// Checks if the current token is in `kinds`.
58 pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
59 kinds.contains(self.current())
60 }
61
62 /// Checks if the current token is contextual keyword with text `t`.
63 pub(crate) fn at_contextual_kw(&self, t: &str) -> bool {
64 self.0.at_kw(t)
65 }
66
67 /// Starts a new node in the syntax tree. All nodes and tokens
68 /// consumed between the `start` and the corresponding `Marker::complete`
69 /// belong to the same node.
70 pub(crate) fn start(&mut self) -> Marker {
71 Marker::new(self.0.start())
72 }
73
74 /// Advances the parser by one token unconditionally.
75 pub(crate) fn bump(&mut self) {
76 self.0.bump();
77 }
78
79 /// Advances the parser by one token, remapping its kind.
80 /// This is useful to create contextual keywords from
81 /// identifiers. For example, the lexer creates an `union`
82 /// *identifier* token, but the parser remaps it to the
83 /// `union` keyword, and keyword is what ends up in the
84 /// final tree.
85 pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
86 self.0.bump_remap(kind);
87 }
88
89 /// Advances the parser by `n` tokens, remapping its kind.
90 /// This is useful to create compound tokens from parts. For
91 /// example, an `<<` token is two consecutive remapped `<` tokens
92 pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
93 self.0.bump_compound(kind, n);
94 }
95
96 /// Emit error with the `message`
97 /// TODO: this should be much more fancy and support
98 /// structured errors with spans and notes, like rustc
99 /// does.
100 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
101 self.0.error(message.into())
102 }
103
104 /// Consume the next token if `kind` matches.
105 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
106 if !self.at(kind) {
107 return false;
108 }
109 self.bump();
110 true
111 }
112
113 /// Consume the next token if it is `kind` or emit an error
114 /// otherwise.
115 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
116 if self.eat(kind) {
117 return true;
118 }
119 self.error(format!("expected {:?}", kind));
120 false
121 }
122
123 /// Create an error node and consume the next token.
124 pub(crate) fn err_and_bump(&mut self, message: &str) {
125 self.err_recover(message, TokenSet::empty());
126 }
127
128 /// Create an error node and consume the next token.
129 pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
130 if self.at(SyntaxKind::L_CURLY) || self.at(SyntaxKind::R_CURLY) || self.at_ts(recovery) {
131 self.error(message);
132 } else {
133 let m = self.start();
134 self.error(message);
135 self.bump();
136 m.complete(self, ERROR);
137 };
138 }
139}
140
141/// See `Parser::start`.
142pub(crate) struct Marker {
143 pos: u32,
144 bomb: DropBomb,
145}
146
147impl Marker {
148 fn new(pos: u32) -> Marker {
149 Marker { pos, bomb: DropBomb::new("Marker must be either completed or abandoned") }
150 }
151
152 /// Finishes the syntax tree node and assigns `kind` to it,
153 /// and mark the create a `CompletedMarker` for possible future
154 /// operation like `.precede()` to deal with forward_parent.
155 pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
156 self.bomb.defuse();
157 p.0.complete(self.pos, kind);
158 CompletedMarker::new(self.pos, kind)
159 }
160
161 /// Abandons the syntax tree node. All its children
162 /// are attached to its parent instead.
163 pub(crate) fn abandon(mut self, p: &mut Parser) {
164 self.bomb.defuse();
165 p.0.abandon(self.pos);
166 }
167}
168
169pub(crate) struct CompletedMarker(u32, SyntaxKind);
170
171impl CompletedMarker {
172 fn new(pos: u32, kind: SyntaxKind) -> Self {
173 CompletedMarker(pos, kind)
174 }
175
176 /// This method allows to create a new node which starts
177 /// *before* the current one. That is, parser could start
178 /// node `A`, then complete it, and then after parsing the
179 /// whole `A`, decide that it should have started some node
180 /// `B` before starting `A`. `precede` allows to do exactly
181 /// that. See also docs about `forward_parent` in `Event::Start`.
182 ///
183 /// Given completed events `[START, FINISH]` and its corresponding
184 /// `CompletedMarker(pos: 0, _)`.
185 /// Append a new `START` events as `[START, FINISH, NEWSTART]`,
186 /// then mark `NEWSTART` as `START`'s parent with saving its relative
187 /// distance to `NEWSTART` into forward_parent(=2 in this case);
188 pub(crate) fn precede(self, p: &mut Parser) -> Marker {
189 Marker::new(p.0.precede(self.0))
190 }
191
192 pub(crate) fn kind(&self) -> SyntaxKind {
193 self.1
194 }
195}