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