rune/parse/
parser.rs

1use core::fmt;
2use core::ops;
3
4use crate::alloc::VecDeque;
5use crate::ast::Spanned;
6use crate::ast::{Kind, OptionSpanned, Span, Token};
7use crate::compile::WithSpan;
8use crate::compile::{self, ErrorKind};
9use crate::macros::{TokenStream, TokenStreamIter};
10use crate::parse::{Advance, Lexer, Parse, Peek};
11use crate::shared::FixedVec;
12use crate::SourceId;
13
14/// Parser for the rune language.
15///
16/// # Examples
17///
18/// ```
19/// use rune::ast;
20/// use rune::SourceId;
21/// use rune::parse::Parser;
22///
23/// let mut parser = Parser::new("fn foo() {}", SourceId::empty(), false);
24/// let ast = parser.parse::<ast::ItemFn>()?;
25/// # Ok::<_, rune::support::Error>(())
26/// ```
27#[derive(Debug)]
28pub struct Parser<'a> {
29    peeker: Peeker<'a>,
30}
31
32impl<'a> Parser<'a> {
33    /// Construct a new parser around the given source.
34    ///
35    /// `shebang` indicates if the parser should try and parse a shebang or not.
36    pub fn new(source: &'a str, source_id: SourceId, shebang: bool) -> Self {
37        Self::with_source(
38            Source {
39                inner: SourceInner::Lexer(Lexer::new(source, source_id, shebang)),
40            },
41            Span::new(0u32, source.len()),
42        )
43    }
44
45    /// Construct a parser from a token stream. The second argument `span` is
46    /// the span to use if the stream is empty.
47    pub fn from_token_stream(token_stream: &'a TokenStream, span: Span) -> Self {
48        Self::with_source(
49            Source {
50                inner: SourceInner::TokenStream(token_stream.iter()),
51            },
52            span,
53        )
54    }
55
56    /// Parse a specific item from the parser.
57    pub fn parse<T>(&mut self) -> compile::Result<T>
58    where
59        T: Parse,
60    {
61        T::parse(self)
62    }
63
64    /// Parse a specific item from the parser and then expect end of input.
65    pub fn parse_all<T>(&mut self) -> compile::Result<T>
66    where
67        T: Parse,
68    {
69        let item = self.parse::<T>()?;
70        self.eof()?;
71        Ok(item)
72    }
73
74    /// Peek for the given token.
75    pub fn peek<T>(&mut self) -> compile::Result<bool>
76    where
77        T: Peek,
78    {
79        if let Some(error) = self.peeker.error.take() {
80            return Err(error);
81        }
82
83        let result = T::peek(&mut self.peeker);
84
85        if let Some(error) = self.peeker.error.take() {
86            return Err(error);
87        }
88
89        Ok(result)
90    }
91
92    /// Assert that the parser has reached its end-of-file.
93    pub fn eof(&mut self) -> compile::Result<()> {
94        if let Some(token) = self.peeker.at(0)? {
95            return Err(compile::Error::new(
96                token,
97                ErrorKind::ExpectedEof { actual: token.kind },
98            ));
99        }
100
101        Ok(())
102    }
103
104    /// Test if the parser is at end-of-file, after which there is no more input
105    /// to parse.
106    pub fn is_eof(&mut self) -> compile::Result<bool> {
107        Ok(self.peeker.at(0)?.is_none())
108    }
109
110    /// Construct a new parser with a source.
111    fn with_source(source: Source<'a>, span: Span) -> Self {
112        let default_span = source.span().unwrap_or(span);
113
114        Self {
115            peeker: Peeker {
116                source,
117                buf: VecDeque::new(),
118                error: None,
119                last: None,
120                default_span,
121            },
122        }
123    }
124
125    /// Try to consume a single thing matching `T`, returns `true` if any tokens
126    /// were consumed.
127    pub fn try_consume<T>(&mut self) -> compile::Result<bool>
128    where
129        T: Parse + Peek,
130    {
131        Ok(if self.peek::<T>()? {
132            self.parse::<T>()?;
133            true
134        } else {
135            false
136        })
137    }
138
139    /// Try to consume all things matching `T`, returns `true` if any tokens
140    /// were consumed.
141    pub fn try_consume_all<T>(&mut self) -> compile::Result<bool>
142    where
143        T: Parse + Peek,
144    {
145        let mut consumed = false;
146
147        while self.peek::<T>()? {
148            self.parse::<T>()?;
149            consumed = true;
150        }
151
152        Ok(consumed)
153    }
154
155    /// Get the span for the given range offset of tokens.
156    pub(crate) fn span(&mut self, range: ops::Range<usize>) -> Span {
157        self.span_at(range.start).join(self.span_at(range.end))
158    }
159
160    /// Access the interior peeker of the parser.
161    pub(crate) fn peeker(&mut self) -> &mut Peeker<'a> {
162        &mut self.peeker
163    }
164
165    /// Consume the next token from the parser.
166    pub(crate) fn next(&mut self) -> compile::Result<Token> {
167        if let Some(error) = self.peeker.error.take() {
168            return Err(error);
169        }
170
171        if let Some(t) = self.peeker.buf.pop_front() {
172            return Ok(t);
173        }
174
175        match self.peeker.next()? {
176            Some(t) => Ok(t),
177            None => Err(compile::Error::new(
178                self.last_span().tail(),
179                ErrorKind::UnexpectedEof,
180            )),
181        }
182    }
183
184    /// Peek the token kind at the given position.
185    pub(crate) fn nth(&mut self, n: usize) -> compile::Result<Kind> {
186        if let Some(t) = self.peeker.at(n)? {
187            Ok(t.kind)
188        } else {
189            Ok(Kind::Eof)
190        }
191    }
192
193    /// Get the span for the given offset.
194    pub(crate) fn span_at(&mut self, n: usize) -> Span {
195        if let Ok(Some(t)) = self.peeker.at(n) {
196            t.span
197        } else {
198            self.last_span().tail()
199        }
200    }
201
202    /// Get the token at the given offset.
203    pub(crate) fn tok_at(&mut self, n: usize) -> compile::Result<Token> {
204        Ok(if let Some(t) = self.peeker.at(n)? {
205            t
206        } else {
207            Token {
208                kind: Kind::Eof,
209                span: self.last_span().tail(),
210            }
211        })
212    }
213
214    /// The last known span in this parser.
215    pub(crate) fn last_span(&self) -> Span {
216        self.peeker.last_span()
217    }
218}
219
220/// Construct used to peek a parser.
221#[derive(Debug)]
222pub struct Peeker<'a> {
223    /// The source being processed.
224    source: Source<'a>,
225    /// The buffer of tokens seen.
226    buf: VecDeque<Token>,
227    // NB: parse errors encountered during peeking.
228    error: Option<compile::Error>,
229    /// The last span we encountered. Used to provide better EOF diagnostics.
230    last: Option<Span>,
231    /// The default span to use in case no better one is available.
232    default_span: Span,
233}
234
235impl Peeker<'_> {
236    /// Peek the token kind at the given position.
237    pub(crate) fn nth(&mut self, n: usize) -> Kind {
238        // Error tripped already, this peeker returns nothing but errors from
239        // here on out.
240        if self.error.is_some() {
241            return Kind::Error;
242        }
243
244        match self.at(n) {
245            Ok(t) => match t {
246                Some(t) => t.kind,
247                None => Kind::Eof,
248            },
249            Err(error) => {
250                self.error = Some(error);
251                Kind::Error
252            }
253        }
254    }
255
256    /// Peek an array.
257    pub(crate) fn array<const N: usize>(&mut self) -> FixedVec<Token, N> {
258        let mut vec = FixedVec::new();
259
260        if N == 0 {
261            return vec;
262        }
263
264        if let Err(error) = self.fill(N) {
265            self.error = Some(error);
266        }
267
268        let mut it = 0..N;
269
270        for (&tok, _) in self.buf.iter().zip(it.by_ref()) {
271            _ = vec.try_push(tok);
272        }
273
274        if let Some(error) = &self.error {
275            for _ in it {
276                _ = vec.try_push(Token {
277                    kind: Kind::Error,
278                    span: error.span(),
279                });
280            }
281        } else {
282            for _ in it {
283                _ = vec.try_push(Token {
284                    kind: Kind::Eof,
285                    span: self.last_span(),
286                });
287            }
288        }
289
290        vec
291    }
292
293    /// Test if we are at end of file.
294    pub(crate) fn is_eof(&mut self) -> bool {
295        match self.at(0) {
296            Ok(t) => t.is_none(),
297            Err(error) => {
298                self.error = Some(error);
299                false
300            }
301        }
302    }
303
304    /// Advance the internals of the peeker and return the next token (without
305    /// buffering).
306    fn next(&mut self) -> compile::Result<Option<Token>> {
307        loop {
308            let Some(token) = self.source.next()? else {
309                return Ok(None);
310            };
311
312            match token.kind {
313                Kind::Comment | Kind::Whitespace => {
314                    continue;
315                }
316                Kind::MultilineComment(term) => {
317                    if !term {
318                        return Err(compile::Error::new(
319                            token.span,
320                            ErrorKind::ExpectedMultilineCommentTerm,
321                        ));
322                    }
323
324                    continue;
325                }
326                _ => (),
327            }
328
329            return Ok(Some(token));
330        }
331    }
332
333    /// Make sure there are at least `n` items in the buffer, and return the
334    /// item at that point.
335    fn at(&mut self, n: usize) -> compile::Result<Option<Token>> {
336        self.fill(n)?;
337        Ok(self.buf.get(n).copied())
338    }
339
340    fn fill(&mut self, n: usize) -> compile::Result<()> {
341        if let Some(error) = self.error.take() {
342            return Err(error);
343        }
344
345        while self.buf.len() <= n {
346            let Some(tok) = self.next()? else {
347                break;
348            };
349
350            self.last = Some(tok.span);
351            self.buf.try_push_back(tok).with_span(tok.span)?;
352        }
353
354        Ok(())
355    }
356
357    /// The last known span in this parser.
358    fn last_span(&self) -> Span {
359        self.last.unwrap_or(self.default_span)
360    }
361}
362
363/// A source adapter.
364pub(crate) struct Source<'a> {
365    inner: SourceInner<'a>,
366}
367
368impl Source<'_> {
369    /// Get the span of the source.
370    fn span(&self) -> Option<Span> {
371        match &self.inner {
372            SourceInner::Lexer(lexer) => Some(lexer.span()),
373            SourceInner::TokenStream(token_stream) => token_stream.option_span(),
374        }
375    }
376
377    /// Get the next token in the stream.
378    fn next(&mut self) -> compile::Result<Option<Token>> {
379        match &mut self.inner {
380            SourceInner::Lexer(lexer) => lexer.next(),
381            SourceInner::TokenStream(token_stream) => Ok(token_stream.next()),
382        }
383    }
384}
385
386impl fmt::Debug for Source<'_> {
387    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388        fmt::Debug::fmt(&self.inner, f)
389    }
390}
391
392#[derive(Debug)]
393enum SourceInner<'a> {
394    Lexer(Lexer<'a>),
395    TokenStream(TokenStreamIter<'a>),
396}
397
398impl Advance for Parser<'_> {
399    type Error = compile::Error;
400
401    #[inline]
402    fn advance(&mut self, n: usize) -> Result<(), Self::Error> {
403        for _ in 0..n {
404            self.next()?;
405        }
406
407        Ok(())
408    }
409}