Skip to main content

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, Options};
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    /// How deep the tree built so far is along the path being parsed.
31    nesting: usize,
32    /// How deep a tree this parser is allowed to produce.
33    max_depth: usize,
34}
35
36impl<'a> Parser<'a> {
37    /// Construct a new parser around the given source.
38    ///
39    /// `shebang` indicates if the parser should try and parse a shebang or not.
40    pub fn new(source: &'a str, source_id: SourceId, shebang: bool) -> Self {
41        Self::with_source(
42            Source {
43                inner: SourceInner::Lexer(Lexer::new(source, source_id, shebang)),
44            },
45            Span::new(0u32, source.len()),
46        )
47    }
48
49    /// Construct a parser from a token stream. The second argument `span` is
50    /// the span to use if the stream is empty.
51    pub fn from_token_stream(token_stream: &'a TokenStream, span: Span) -> Self {
52        Self::with_source(
53            Source {
54                inner: SourceInner::TokenStream(token_stream.iter()),
55            },
56            span,
57        )
58    }
59
60    /// Parse a specific item from the parser.
61    pub fn parse<T>(&mut self) -> compile::Result<T>
62    where
63        T: Parse,
64    {
65        T::parse(self)
66    }
67
68    /// Configure how deep a tree this parser is allowed to produce.
69    ///
70    /// Defaults to the `max-ast-depth` option's default. A macro which is
71    /// handed the compiler's options through its [`MacroContext`] should
72    /// configure the parser it builds from them, which
73    /// [`MacroContext::parser`] does.
74    ///
75    /// [`MacroContext`]: crate::macros::MacroContext
76    /// [`MacroContext::parser`]: crate::macros::MacroContext::parser
77    pub fn with_max_depth(mut self, max_depth: usize) -> Self {
78        self.max_depth = max_depth;
79        self
80    }
81
82    /// Parse one level deeper, ensuring that the tree being built does not get
83    /// deeper than the parser allows.
84    ///
85    /// Every recursive path through the syntax tree descends through here, so
86    /// that input which is too deep is reported as a diagnostic rather than
87    /// overflowing the stack, either while it is being parsed or later while it
88    /// is being walked.
89    ///
90    /// The level is *restored* rather than decremented on the way out, so that
91    /// the links [`Parser::link`] accounts for are released along with the
92    /// expression they belong to.
93    pub(crate) fn nested<T>(
94        &mut self,
95        parse: impl FnOnce(&mut Self) -> compile::Result<T>,
96    ) -> compile::Result<T> {
97        let nesting = self.nesting;
98        self.deepen()?;
99        let result = parse(self);
100        self.nesting = nesting;
101        result
102    }
103
104    /// Account for one more link of a chain.
105    ///
106    /// A chain is parsed over a loop rather than by recursing, so it costs no
107    /// parser frames, but each link is another level of the tree which is left
108    /// behind. The level is released by the enclosing [`Parser::nested`], which
109    /// is the expression the chain belongs to.
110    pub(crate) fn link(&mut self) -> compile::Result<()> {
111        self.deepen()
112    }
113
114    fn deepen(&mut self) -> compile::Result<()> {
115        if self.nesting >= self.max_depth {
116            return Err(compile::Error::new(
117                self.span_at(0),
118                ErrorKind::MaxAstDepth {
119                    max: self.max_depth,
120                },
121            ));
122        }
123
124        self.nesting += 1;
125        Ok(())
126    }
127
128    /// Parse a specific item from the parser and then expect end of input.
129    pub fn parse_all<T>(&mut self) -> compile::Result<T>
130    where
131        T: Parse,
132    {
133        let item = self.parse::<T>()?;
134        self.eof()?;
135        Ok(item)
136    }
137
138    /// Peek for the given token.
139    pub fn peek<T>(&mut self) -> compile::Result<bool>
140    where
141        T: Peek,
142    {
143        if let Some(error) = self.peeker.error.take() {
144            return Err(error);
145        }
146
147        let result = T::peek(&mut self.peeker);
148
149        if let Some(error) = self.peeker.error.take() {
150            return Err(error);
151        }
152
153        Ok(result)
154    }
155
156    /// Assert that the parser has reached its end-of-file.
157    pub fn eof(&mut self) -> compile::Result<()> {
158        if let Some(token) = self.peeker.at(0)? {
159            return Err(compile::Error::new(
160                token,
161                ErrorKind::ExpectedEof { actual: token.kind },
162            ));
163        }
164
165        Ok(())
166    }
167
168    /// Test if the parser is at end-of-file, after which there is no more input
169    /// to parse.
170    pub fn is_eof(&mut self) -> compile::Result<bool> {
171        Ok(self.peeker.at(0)?.is_none())
172    }
173
174    /// Construct a new parser with a source.
175    fn with_source(source: Source<'a>, span: Span) -> Self {
176        let default_span = source.span().unwrap_or(span);
177
178        Self {
179            peeker: Peeker {
180                source,
181                buf: VecDeque::new(),
182                error: None,
183                last: None,
184                default_span,
185            },
186            nesting: 0,
187            max_depth: Options::DEFAULT.max_ast_depth,
188        }
189    }
190
191    /// Try to consume a single thing matching `T`, returns `true` if any tokens
192    /// were consumed.
193    pub fn try_consume<T>(&mut self) -> compile::Result<bool>
194    where
195        T: Parse + Peek,
196    {
197        Ok(if self.peek::<T>()? {
198            self.parse::<T>()?;
199            true
200        } else {
201            false
202        })
203    }
204
205    /// Try to consume all things matching `T`, returns `true` if any tokens
206    /// were consumed.
207    pub fn try_consume_all<T>(&mut self) -> compile::Result<bool>
208    where
209        T: Parse + Peek,
210    {
211        let mut consumed = false;
212
213        while self.peek::<T>()? {
214            self.parse::<T>()?;
215            consumed = true;
216        }
217
218        Ok(consumed)
219    }
220
221    /// Get the span for the given range offset of tokens.
222    pub(crate) fn span(&mut self, range: ops::Range<usize>) -> Span {
223        self.span_at(range.start).join(self.span_at(range.end))
224    }
225
226    /// Access the interior peeker of the parser.
227    pub(crate) fn peeker(&mut self) -> &mut Peeker<'a> {
228        &mut self.peeker
229    }
230
231    /// Consume the next token from the parser.
232    pub(crate) fn next(&mut self) -> compile::Result<Token> {
233        if let Some(error) = self.peeker.error.take() {
234            return Err(error);
235        }
236
237        if let Some(t) = self.peeker.buf.pop_front() {
238            return Ok(t);
239        }
240
241        match self.peeker.next()? {
242            Some(t) => Ok(t),
243            None => Err(compile::Error::new(
244                self.last_span().tail(),
245                ErrorKind::UnexpectedEof,
246            )),
247        }
248    }
249
250    /// Peek the token kind at the given position.
251    pub(crate) fn nth(&mut self, n: usize) -> compile::Result<Kind> {
252        if let Some(t) = self.peeker.at(n)? {
253            Ok(t.kind)
254        } else {
255            Ok(Kind::Eof)
256        }
257    }
258
259    /// Get the span for the given offset.
260    pub(crate) fn span_at(&mut self, n: usize) -> Span {
261        if let Ok(Some(t)) = self.peeker.at(n) {
262            t.span
263        } else {
264            self.last_span().tail()
265        }
266    }
267
268    /// Get the token at the given offset.
269    pub(crate) fn tok_at(&mut self, n: usize) -> compile::Result<Token> {
270        Ok(if let Some(t) = self.peeker.at(n)? {
271            t
272        } else {
273            Token {
274                kind: Kind::Eof,
275                span: self.last_span().tail(),
276            }
277        })
278    }
279
280    /// The last known span in this parser.
281    pub(crate) fn last_span(&self) -> Span {
282        self.peeker.last_span()
283    }
284}
285
286/// Construct used to peek a parser.
287#[derive(Debug)]
288pub struct Peeker<'a> {
289    /// The source being processed.
290    source: Source<'a>,
291    /// The buffer of tokens seen.
292    buf: VecDeque<Token>,
293    // NB: parse errors encountered during peeking.
294    error: Option<compile::Error>,
295    /// The last span we encountered. Used to provide better EOF diagnostics.
296    last: Option<Span>,
297    /// The default span to use in case no better one is available.
298    default_span: Span,
299}
300
301impl Peeker<'_> {
302    /// Peek the token kind at the given position.
303    pub(crate) fn nth(&mut self, n: usize) -> Kind {
304        // Error tripped already, this peeker returns nothing but errors from
305        // here on out.
306        if self.error.is_some() {
307            return Kind::Error;
308        }
309
310        match self.at(n) {
311            Ok(t) => match t {
312                Some(t) => t.kind,
313                None => Kind::Eof,
314            },
315            Err(error) => {
316                self.error = Some(error);
317                Kind::Error
318            }
319        }
320    }
321
322    /// Peek an array.
323    pub(crate) fn array<const N: usize>(&mut self) -> FixedVec<Token, N> {
324        let mut vec = FixedVec::new();
325
326        if N == 0 {
327            return vec;
328        }
329
330        if let Err(error) = self.fill(N) {
331            self.error = Some(error);
332        }
333
334        let mut it = 0..N;
335
336        for (&tok, _) in self.buf.iter().zip(it.by_ref()) {
337            _ = vec.try_push(tok);
338        }
339
340        if let Some(error) = &self.error {
341            for _ in it {
342                _ = vec.try_push(Token {
343                    kind: Kind::Error,
344                    span: error.span(),
345                });
346            }
347        } else {
348            for _ in it {
349                _ = vec.try_push(Token {
350                    kind: Kind::Eof,
351                    span: self.last_span(),
352                });
353            }
354        }
355
356        vec
357    }
358
359    /// Test if we are at end of file.
360    pub(crate) fn is_eof(&mut self) -> bool {
361        match self.at(0) {
362            Ok(t) => t.is_none(),
363            Err(error) => {
364                self.error = Some(error);
365                false
366            }
367        }
368    }
369
370    /// Advance the internals of the peeker and return the next token (without
371    /// buffering).
372    fn next(&mut self) -> compile::Result<Option<Token>> {
373        loop {
374            let Some(token) = self.source.next()? else {
375                return Ok(None);
376            };
377
378            match token.kind {
379                Kind::Comment | Kind::Whitespace => {
380                    continue;
381                }
382                Kind::MultilineComment(term) => {
383                    if !term {
384                        return Err(compile::Error::new(
385                            token.span,
386                            ErrorKind::ExpectedMultilineCommentTerm,
387                        ));
388                    }
389
390                    continue;
391                }
392                _ => (),
393            }
394
395            return Ok(Some(token));
396        }
397    }
398
399    /// Make sure there are at least `n` items in the buffer, and return the
400    /// item at that point.
401    fn at(&mut self, n: usize) -> compile::Result<Option<Token>> {
402        self.fill(n)?;
403        Ok(self.buf.get(n).copied())
404    }
405
406    fn fill(&mut self, n: usize) -> compile::Result<()> {
407        if let Some(error) = self.error.take() {
408            return Err(error);
409        }
410
411        while self.buf.len() <= n {
412            let Some(tok) = self.next()? else {
413                break;
414            };
415
416            self.last = Some(tok.span);
417            self.buf.try_push_back(tok).with_span(tok.span)?;
418        }
419
420        Ok(())
421    }
422
423    /// The last known span in this parser.
424    fn last_span(&self) -> Span {
425        self.last.unwrap_or(self.default_span)
426    }
427}
428
429/// A source adapter.
430pub(crate) struct Source<'a> {
431    inner: SourceInner<'a>,
432}
433
434impl Source<'_> {
435    /// Get the span of the source.
436    fn span(&self) -> Option<Span> {
437        match &self.inner {
438            SourceInner::Lexer(lexer) => Some(lexer.span()),
439            SourceInner::TokenStream(token_stream) => token_stream.option_span(),
440        }
441    }
442
443    /// Get the next token in the stream.
444    fn next(&mut self) -> compile::Result<Option<Token>> {
445        match &mut self.inner {
446            SourceInner::Lexer(lexer) => lexer.next(),
447            SourceInner::TokenStream(token_stream) => Ok(token_stream.next()),
448        }
449    }
450}
451
452impl fmt::Debug for Source<'_> {
453    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454        fmt::Debug::fmt(&self.inner, f)
455    }
456}
457
458#[derive(Debug)]
459enum SourceInner<'a> {
460    Lexer(Lexer<'a>),
461    TokenStream(TokenStreamIter<'a>),
462}
463
464impl Advance for Parser<'_> {
465    type Error = compile::Error;
466
467    #[inline]
468    fn advance(&mut self, n: usize) -> Result<(), Self::Error> {
469        for _ in 0..n {
470            self.next()?;
471        }
472
473        Ok(())
474    }
475}