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, constraint clause follows.
39 Ok(_t)
40 if parser
41 .peek_next_not_whitespace()
42 .is_some_and(|t| t.variant == TokenTy::KwConstrain) =>
43 {
44 // Consume whitespace
45 parser.consume_at_least_one_whitespace()?;
46
47 // consume constrain keyword
48 assert_eq!(parser.next_token().unwrap().unwrap().variant, TokenTy::KwConstrain);
49
50 // let mut constraints: Vec<Identifier> = Vec::new();
51
52 // FIXME: This sucks for parsing and I'm increasingly thinking the syntax for constraints
53 // should be `type ~ a ~ b ~ c...` rather than `type constrain a, b, c`
54 while let Some(peek) = parser.peek_next_not_whitespace()
55 && peek.variant == TokenTy::Identifier
56 {}
57 }
58
59 // Successful parse, no constraint clause.
60 Ok(t) => return Ok(t),
61
62 // Partial parse with error.
63 Err(err) if parser.bytes_remaining() != initial_bytes_remaining => return Err(err),
64
65 // Parsing error with no tokens consumed.
66 Err(_) => continue,
67 }
68 }
69
70 Err(ParserErrorKind::ExpectedTypeSignature.at(parser.peek_fragment_or_rest_cloned()))
71 }
72}