1use luau_lexer::prelude::{Keyword, Lexer, ParseError, PartialKeyword, Symbol, Token, TokenType};
8
9use crate::{
10 force_parse_bracketed, parse_bracketed,
11 types::{
12 Attribute, Block, GetRange, GetRangeError, GlobalFunction, GlobalFunctionName,
13 LocalFunction, Parameter, Parse, ParseWithArgs, Pointer, Range, TableAccessKey, TryParse,
14 TryParseWithArgs, TypeFunction, TypeValue,
15 },
16 utils::{get_token_type_display, get_token_type_display_extended},
17};
18
19impl Parse for LocalFunction {
20 fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
21 let state = lexer.save_state();
22 let attributes;
23 let local_keyword;
24
25 match token.token_type {
26 TokenType::Keyword(Keyword::Local) => {
27 attributes = Vec::new();
28 local_keyword = token;
29 }
30 TokenType::Symbol(Symbol::At) => {
31 attributes = safe_unwrap!(
32 lexer,
33 errors,
34 "Expected <attribute>",
35 Vec::parse(token, lexer, errors)
36 );
37 local_keyword = lexer.next_token();
38 }
39 _ => return None,
40 }
41 if local_keyword != TokenType::Keyword(Keyword::Local) {
42 lexer.set_state(state);
43
44 return None;
45 }
46
47 parse_function!(
48 let attributes = attributes;
49 lexer.next_token(),
50 lexer,
51 errors,
52 let function_name = {
53 next_token_recoverable!(
54 lexer,
55 name,
56 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
57 TokenType::Identifier("*error*".into(),),
58 errors,
59 "Expected ".to_string()
60 + get_token_type_display(&TokenType::Identifier("".into(),))
61 );
62
63 name
64 },
65 { attributes, local_keyword, function_name }
66 )
67 }
68}
69impl TryParse for LocalFunction {}
70
71impl Parse for GlobalFunctionName {
72 fn parse(name: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
73 if !matches!(
74 name.token_type,
75 TokenType::Identifier(_) | TokenType::PartialKeyword(_)
76 ) {
77 return None;
78 }
79
80 maybe_next_token!(
81 lexer,
82 dot_or_colon,
83 TokenType::Symbol(Symbol::Dot) | TokenType::Symbol(Symbol::Colon)
84 );
85 if let Some(dot_or_colon) = dot_or_colon {
86 let is_dot = dot_or_colon == TokenType::Symbol(Symbol::Dot);
87
88 let keys = if is_dot {
89 Vec::<TableAccessKey>::parse_with(dot_or_colon.clone(), lexer, errors, false)
90 .unwrap_or_default()
91 } else {
92 Vec::new()
93 };
94
95 let method = if !is_dot {
96 next_token_recoverable!(
97 lexer,
98 parsed_method,
99 TokenType::Identifier(_),
100 TokenType::Identifier("*error*".into()),
101 errors,
102 "Expected ".to_string()
103 + get_token_type_display(&TokenType::Identifier("".into()),)
104 );
105
106 Some(Pointer::new((dot_or_colon, parsed_method)))
107 } else {
108 None
109 };
110
111 return Some(Self::Table {
112 table: name,
113 keys,
114 method,
115 });
116 }
117
118 Some(Self::SimpleName(name))
119 }
120}
121impl TryParse for GlobalFunctionName {}
122
123impl Parse for GlobalFunction {
124 fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
125 let attributes;
126 let function_keyword;
127
128 match token.token_type {
129 TokenType::Keyword(Keyword::Function) => {
130 attributes = Vec::new();
131 function_keyword = token;
132 }
133 TokenType::Symbol(Symbol::At) => {
134 attributes = safe_unwrap!(
135 lexer,
136 errors,
137 "Expected <attribute>",
138 Vec::parse(token, lexer, errors)
139 );
140 function_keyword = lexer.next_token();
141 }
142 _ => return None,
143 }
144
145 parse_function!(
146 let attributes = attributes;
147 function_keyword,
148 lexer,
149 errors,
150 let function_name = {
151 GlobalFunctionName::try_parse(lexer, errors).unwrap_or_else(|| {
152 GlobalFunctionName::SimpleName(Token::empty(TokenType::Identifier(
153 "*error*".into(),
154 )))
155 })
156 },
157 { attributes, function_name }
158 )
159 }
160}
161impl TryParse for GlobalFunction {}
162
163impl Parse for Parameter {
164 fn parse(name: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
165 if !matches!(
166 name.token_type,
167 TokenType::Identifier(_)
168 | TokenType::PartialKeyword(_)
169 | TokenType::Symbol(Symbol::Ellipses)
170 ) {
171 return None;
172 }
173
174 maybe_next_token!(lexer, colon, TokenType::Symbol(Symbol::Colon));
175
176 let r#type = if colon.is_some() {
177 Pointer::<TypeValue>::try_parse(lexer, errors)
178 } else {
179 None
180 };
181
182 Some(Self {
183 name,
184 colon,
185 r#type,
186 })
187 }
188}
189
190impl Parse for Attribute {
191 fn parse(at: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
192 if at != TokenType::Symbol(Symbol::At) {
193 return None;
194 }
195
196 next_token_recoverable!(
197 lexer,
198 attribute,
199 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
200 TokenType::Identifier("*error*".into()),
201 errors,
202 "Expected ".to_string() + get_token_type_display(&TokenType::Identifier("".into()))
203 );
204
205 Some(Self { at, attribute })
206 }
207}
208impl TryParse for Attribute {}
209
210impl GetRange for GlobalFunctionName {
211 fn get_range(&self) -> Result<Range, GetRangeError> {
212 match self {
213 GlobalFunctionName::SimpleName(token) => token.get_range(),
214 GlobalFunctionName::Table {
215 table,
216 keys,
217 method,
218 } => {
219 let table_range = table.get_range();
220 let last_range = match method {
221 Some(method) => method.1.get_range(),
222 None => keys.get_range(),
223 };
224
225 if let Ok(last_range) = last_range {
226 Ok(Range::new(table_range?.start, last_range.end))
227 } else {
228 table_range
229 }
230 }
231 }
232 }
233}
234
235impl Parse for TypeFunction {
236 fn parse(
237 mut type_keyword: Token,
238 lexer: &mut Lexer,
239 errors: &mut Vec<ParseError>,
240 ) -> Option<Self> {
241 let state = lexer.save_state();
242
243 let export_keyword = if type_keyword == TokenType::PartialKeyword(PartialKeyword::Export) {
244 let temp = type_keyword;
245 type_keyword = lexer.next_token();
246
247 Some(temp)
248 } else {
249 None
250 };
251
252 let function_keyword = lexer.next_token();
253
254 if type_keyword != TokenType::PartialKeyword(PartialKeyword::Type)
255 || function_keyword != TokenType::Keyword(Keyword::Function)
256 {
257 lexer.set_state(state);
258
259 return None;
260 }
261
262 parse_function!(
263 function_keyword,
264 lexer,
265 errors,
266 let function_name = {
267 next_token_recoverable!(
268 lexer,
269 name,
270 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
271 TokenType::Identifier("*error*".into(),),
272 errors,
273 "Expected ".to_string()
274 + get_token_type_display(&TokenType::Identifier("".into(),))
275 );
276
277 name
278 },
279 { export_keyword, type_keyword, function_name }
280 )
281 }
282}
283impl TryParse for TypeFunction {}