wright/parser/
ty.rs

1//! Parser implementation for parsing types.
2
3use crate::{
4    ast::{
5        // identifier::Identifier,
6        ty::{AtomicTy, ReferenceTy, Type},
7    },
8    lexer::token::TokenTy,
9};
10
11use super::{
12    Parser,
13    error::{ParserError, ParserErrorKind},
14};
15
16mod constrained_ty;
17mod primitive;
18mod reference;
19
20impl Type {
21    /// Parse a type signature in source code.
22    pub fn parse(parser: &mut Parser) -> Result<Self, ParserError> {
23        // First try to parse a type, then check to see if the `constrain` keyword follows it,
24        // since that's effectively a type suffix.
25
26        // Atempt to parse atomic types first -- they're the simplest. If we fail to parse, the parser doesn't advance.
27        // Since they're all keywords we don't have to worry at all about under-greedy parsing (yet).
28        let atomic_ty_parse_fn = |parser: &mut Parser| AtomicTy::parse(parser).map(Type::Atomic);
29        let reference_ty_parse_fn =
30            |parser: &mut Parser| ReferenceTy::parse(parser).map(Type::Reference);
31
32        let order = [atomic_ty_parse_fn, reference_ty_parse_fn];
33
34        for parse_fn in order {
35            let initial_bytes_remaining = parser.bytes_remaining();
36
37            match (parse_fn)(parser) {
38                // Successful parse.
39                Ok(t) => return Ok(t),
40
41                // Partial parse with error.
42                Err(err) if parser.bytes_remaining() != initial_bytes_remaining => return Err(err),
43
44                // Parsing error with no tokens consumed.
45                Err(_) => continue,
46            }
47        }
48
49        Err(ParserErrorKind::ExpectedTypeSignature.at(parser.peek_fragment_or_rest_cloned()))
50    }
51}