wright/parser/
ty.rs

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