ara_parser/parser/internal/definition/
template.rs

1use crate::lexer::token::TokenKind;
2use crate::parser::internal::definition::r#type;
3use crate::parser::internal::identifier;
4use crate::parser::internal::utils;
5use crate::parser::result::ParseResult;
6use crate::parser::state::State;
7use crate::tree::definition::template::TemplateDefinition;
8use crate::tree::definition::template::TemplateDefinitionTypeConstraint;
9use crate::tree::definition::template::TemplateDefinitionVariance;
10use crate::tree::definition::template::TemplateGroupDefinition;
11use crate::tree::definition::template::TypeTemplateGroupDefinition;
12use crate::tree::utils::CommaSeparated;
13
14pub fn template_group_definition(state: &mut State) -> ParseResult<TemplateGroupDefinition> {
15    Ok(TemplateGroupDefinition {
16        comments: state.iterator.comments(),
17        less_than: utils::skip(state, TokenKind::LessThan)?,
18        members: {
19            let mut inner = vec![];
20            let mut commas = vec![];
21
22            let mut current = state.iterator.current();
23            while current.kind != TokenKind::GreaterThan && current.kind != TokenKind::RightShift {
24                inner.push({
25                    let current = state.iterator.current();
26                    let variance = match &current.kind {
27                        TokenKind::Plus => {
28                            state.iterator.next();
29
30                            TemplateDefinitionVariance::Covariance(current.position)
31                        }
32                        _ => TemplateDefinitionVariance::Invaraint,
33                    };
34
35                    let name = identifier::classname_identifier(state)?;
36
37                    let current = state.iterator.current();
38                    let constraint = match &current.kind {
39                        TokenKind::As => TemplateDefinitionTypeConstraint::SubType(
40                            utils::skip_keyword(state, TokenKind::As)?,
41                            r#type::type_definition(state)?,
42                        ),
43                        _ => TemplateDefinitionTypeConstraint::None,
44                    };
45
46                    TemplateDefinition {
47                        name,
48                        variance,
49                        constraint,
50                    }
51                });
52
53                current = state.iterator.current();
54                if current.kind != TokenKind::Comma {
55                    break;
56                }
57
58                commas.push(current.position);
59
60                state.iterator.next();
61                current = state.iterator.current();
62            }
63
64            CommaSeparated { inner, commas }
65        },
66        greater_than: {
67            let current = state.iterator.current();
68
69            if let Some(token) = state.ignored_shift_at {
70                utils::skip(state, TokenKind::RightShift)?;
71                state.ignored_shift_at = None;
72                token.position + 1
73            } else if current.kind == TokenKind::RightShift {
74                state.ignored_shift_at = Some(current);
75
76                current.position
77            } else {
78                utils::skip(state, TokenKind::GreaterThan)?
79            }
80        },
81    })
82}
83
84pub fn type_template_group_definition(
85    state: &mut State,
86) -> ParseResult<TypeTemplateGroupDefinition> {
87    let comments = state.iterator.comments();
88    let less_than = utils::skip(state, TokenKind::LessThan)?;
89
90    let members = {
91        let mut inner = vec![];
92        let mut commas = vec![];
93
94        let mut current = state.iterator.current();
95        while current.kind != TokenKind::GreaterThan && current.kind != TokenKind::RightShift {
96            inner.push(r#type::type_definition(state)?);
97
98            current = state.iterator.current();
99            if current.kind != TokenKind::Comma {
100                break;
101            }
102
103            commas.push(current.position);
104
105            state.iterator.next();
106            current = state.iterator.current();
107        }
108
109        CommaSeparated { inner, commas }
110    };
111
112    let greater_than = {
113        let current = state.iterator.current();
114
115        if let Some(token) = state.ignored_shift_at {
116            utils::skip(state, TokenKind::RightShift)?;
117            state.ignored_shift_at = None;
118            token.position + 1
119        } else if current.kind == TokenKind::RightShift {
120            state.ignored_shift_at = Some(current);
121
122            current.position
123        } else {
124            utils::skip(state, TokenKind::GreaterThan)?
125        }
126    };
127
128    Ok(TypeTemplateGroupDefinition {
129        comments,
130        less_than,
131        members,
132        greater_than,
133    })
134}