luau_parser/impl/
mod.rs

1//! All `impl` blocks for CST-related types.
2
3#[macro_use]
4mod macros;
5
6mod block;
7mod bracketed;
8mod cst;
9mod expression;
10mod list;
11mod literals;
12mod name;
13mod range;
14mod value;
15
16use luau_lexer::prelude::{Lexer, ParseError, Token};
17
18use crate::types::{
19    GetRange, GetRangeError, Parse, ParseWithArgs, Pointer, Print, Range, TryParse,
20    TryParseWithArgs,
21};
22
23impl<T: Parse> Parse for Pointer<T> {
24    #[inline]
25    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
26        T::parse(token, lexer, errors).map(Self::new)
27    }
28}
29impl<T: TryParse + Parse> TryParse for Pointer<T> {
30    #[inline]
31    fn try_parse(lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
32        T::try_parse(lexer, errors).map(Self::new)
33    }
34}
35
36impl<T: Parse> Parse for Vec<T> {
37    #[inline]
38    fn parse(mut token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
39        let mut values = Vec::new();
40        let mut state = lexer.save_state();
41
42        while let Some(value) = T::parse(token, lexer, errors) {
43            values.push(value);
44            state = lexer.save_state();
45            token = lexer.next_token();
46        }
47
48        lexer.set_state(state);
49
50        (!values.is_empty()).then_some(values)
51    }
52}
53impl<T: TryParse + Parse> TryParse for Vec<T> {}
54
55impl<T: ParseWithArgs<A>, A: Clone> ParseWithArgs<A> for Vec<T> {
56    #[inline]
57    fn parse_with(
58        mut token: Token,
59        lexer: &mut Lexer,
60        errors: &mut Vec<ParseError>,
61        args: A,
62    ) -> Option<Self> {
63        let mut values = Vec::new();
64        let mut state = lexer.save_state();
65
66        while let Some(value) = T::parse_with(token, lexer, errors, args.clone()) {
67            values.push(value);
68            state = lexer.save_state();
69            token = lexer.next_token();
70        }
71
72        lexer.set_state(state);
73
74        (!values.is_empty()).then_some(values)
75    }
76}
77impl<T: ParseWithArgs<A>, A: Clone> TryParseWithArgs<A> for T {}
78
79impl GetRange for Token {
80    #[inline]
81    fn get_range(&self) -> Result<Range, GetRangeError> {
82        Ok(Range::new(self.start, self.end))
83    }
84}
85impl Print for Token {
86    #[inline]
87    fn print(&self) -> String {
88        self.token_type
89            .try_as_string()
90            .map(|token_type| self.spaces_before.to_string() + &token_type + &self.spaces_after)
91            .unwrap_or_default()
92    }
93}
94
95impl<T: GetRange> GetRange for Pointer<T> {
96    #[inline]
97    fn get_range(&self) -> Result<Range, GetRangeError> {
98        (**self).get_range()
99    }
100}
101impl<T: Print> Print for Pointer<T> {
102    #[inline]
103    fn print(&self) -> String {
104        (**self).print()
105    }
106}
107
108impl<T: Print> Print for Option<T> {
109    #[inline]
110    fn print(&self) -> String {
111        match self {
112            Some(item) => item.print(),
113            None => "".to_string(),
114        }
115    }
116}
117
118impl<T: GetRange> GetRange for Vec<T> {
119    #[inline]
120    fn get_range(&self) -> Result<Range, GetRangeError> {
121        if self.is_empty() {
122            Err(GetRangeError::EmptyList)
123        } else if self.len() == 1 {
124            self[0].get_range()
125        } else {
126            Ok(Range::new(
127                self[0].get_range()?.start,
128                self.last().unwrap().get_range()?.end,
129            ))
130        }
131    }
132}
133impl<T: Print> Print for Vec<T> {
134    fn print(&self) -> String {
135        self.iter().fold("".to_string(), |str, item| {
136            str.trim_end().to_string() + &item.print()
137        })
138    }
139}
140
141impl<T: Print, U: Print> Print for (T, U) {
142    #[inline]
143    fn print(&self) -> String {
144        let end = self.1.print();
145
146        if end.is_empty() {
147            self.0.print()
148        } else {
149            self.0.print().trim_end().to_string() + &end
150        }
151    }
152}