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