luau_parser/impl/
list.rs

1//! All `impl` blocks for [`List`].
2
3use luau_lexer::prelude::{Lexer, ParseError, Symbol, Token, TokenType};
4use std::ops::{Deref, DerefMut};
5
6use crate::types::{
7    GetRange, GetRangeError, List, ListItem, Parse, ParseWithArgs, Print, Range, TryParse,
8};
9
10impl<T> List<T> {
11    /// Create a new empty list.
12    #[inline]
13    pub const fn new() -> Self {
14        Self { items: Vec::new() }
15    }
16
17    /// The main parsing logic.
18    fn parse<C: FnMut(Token, &mut Lexer) -> Option<T>>(
19        mut token: Token,
20        lexer: &mut Lexer,
21        mut parse: C,
22    ) -> Option<Self> {
23        let mut items = Vec::new();
24        let mut state = lexer.save_state();
25
26        while let Some(item) = parse(token, lexer) {
27            maybe_next_token!(lexer, maybe_comma, TokenType::Symbol(Symbol::Comma));
28            state = lexer.save_state();
29
30            if let Some(comma) = maybe_comma {
31                items.push(ListItem::Trailing {
32                    item,
33                    separator: comma,
34                });
35            } else {
36                items.push(ListItem::NonTrailing(item));
37
38                break;
39            }
40
41            token = lexer.next_token();
42        }
43
44        lexer.set_state(state);
45
46        Some(Self { items })
47    }
48}
49
50impl<T> Default for List<T> {
51    #[inline]
52    fn default() -> Self {
53        Self::new()
54    }
55}
56
57impl<T: Parse> Parse for List<T> {
58    #[inline]
59    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
60        Self::parse(token, lexer, |token, lexer| T::parse(token, lexer, errors))
61    }
62}
63impl<T: Parse> TryParse for List<T> {}
64
65impl<A: Clone, T: ParseWithArgs<A>> ParseWithArgs<A> for List<T> {
66    #[inline]
67    fn parse_with(
68        token: Token,
69        lexer: &mut Lexer,
70        errors: &mut Vec<ParseError>,
71        args: A,
72    ) -> Option<Self> {
73        Self::parse(token, lexer, |token, lexer| {
74            T::parse_with(token, lexer, errors, args.clone())
75        })
76    }
77}
78
79impl<T> Deref for List<T> {
80    type Target = Vec<ListItem<T>>;
81
82    fn deref(&self) -> &Self::Target {
83        &self.items
84    }
85}
86impl<T> DerefMut for List<T> {
87    fn deref_mut(&mut self) -> &mut Self::Target {
88        &mut self.items
89    }
90}
91
92impl<T> Deref for ListItem<T> {
93    type Target = T;
94
95    fn deref(&self) -> &Self::Target {
96        match self {
97            ListItem::Trailing { item, .. } => item,
98            ListItem::NonTrailing(item) => item,
99        }
100    }
101}
102impl<T> DerefMut for ListItem<T> {
103    fn deref_mut(&mut self) -> &mut Self::Target {
104        match self {
105            ListItem::Trailing { item, .. } => item,
106            ListItem::NonTrailing(item) => item,
107        }
108    }
109}
110
111impl<T: GetRange> GetRange for List<T> {
112    fn get_range(&self) -> Result<Range, GetRangeError> {
113        (**self).get_range()
114    }
115}
116
117impl<T: GetRange> GetRange for ListItem<T> {
118    fn get_range(&self) -> Result<Range, GetRangeError> {
119        match self {
120            ListItem::Trailing { item, separator } => Ok(Range::new(
121                item.get_range()?.start,
122                separator.get_range()?.end,
123            )),
124            ListItem::NonTrailing(item) => item.get_range(),
125        }
126    }
127}
128
129impl<T: Print> Print for List<T> {
130    #[inline]
131    fn print(&self) -> String {
132        self.items.print()
133    }
134
135    #[inline]
136    fn print_final_trivia(&self) -> String {
137        self.items.print_final_trivia()
138    }
139
140    #[inline]
141    fn print_without_final_trivia(&self) -> String {
142        self.items.print_without_final_trivia()
143    }
144}
145
146impl<T: Print> Print for ListItem<T> {
147    #[inline]
148    fn print(&self) -> String {
149        match self {
150            Self::Trailing { item, separator } => {
151                item.print_without_final_trivia() + &separator.print()
152            }
153            Self::NonTrailing(item) => item.print(),
154        }
155    }
156
157    #[inline]
158    fn print_final_trivia(&self) -> String {
159        match self {
160            ListItem::Trailing { separator, .. } => separator.print_final_trivia(),
161            ListItem::NonTrailing(item) => item.print_final_trivia(),
162        }
163    }
164
165    #[inline]
166    fn print_without_final_trivia(&self) -> String {
167        match self {
168            ListItem::Trailing { item, separator } => {
169                item.print_without_final_trivia() + &separator.print_without_final_trivia()
170            }
171            ListItem::NonTrailing(item) => item.print_without_final_trivia(),
172        }
173    }
174}