1use alloc::vec::Vec;
2
3use super::Parser;
4use crate::{
5 ast::*,
6 lexer::Token,
7 marker::LuaVersion,
8 ParseError,
9};
10
11impl<'src, V: LuaVersion> Parser<'src, V> {
12 pub(super) fn parse_identifier(&mut self) -> Result<Identifier, ParseError> {
13 let name = match self.current() {
14 Token::Identifier(name) => name.clone(),
15 Token::Continue if !V::HAS_CONTINUE => "continue".to_string(),
16 Token::Export if !V::HAS_EXPORT => "export".to_string(),
17 Token::Type if !V::HAS_TYPE_ANNOTATIONS => "type".to_string(),
18 Token::Goto if !V::HAS_GOTO => "goto".to_string(),
19 _ => {
21 return Err(ParseError::UnexpectedToken {
22 expected: alloc::vec!["identifier".to_string()],
23 found: alloc::format!("{:?}", self.current()),
24 span: self.current_span(),
25 });
26 }
27 };
28
29 let span = self.current_span();
30 self.advance();
31 Ok(Identifier::new(name, span))
32 }
33
34 pub(super) fn can_be_identifier(&self, token: &Token) -> bool {
35 match token {
36 Token::Identifier(_) => true,
37 Token::Continue => !V::HAS_CONTINUE,
38 Token::Export => !V::HAS_EXPORT,
39 Token::Type => !V::HAS_TYPE_ANNOTATIONS,
40 Token::Goto => !V::HAS_GOTO,
41 Token::Const => !V::HAS_CONST,
42 _ => false,
43 }
44 }
45
46 pub(super) fn parse_block_until(&mut self, terminators: &[Token]) -> Result<Block, ParseError> {
47 let start = self.current_span().start;
48 let mut statements = Vec::new();
49
50 while !self.is_eof() {
51 self.skip_comments();
52
53 if terminators.contains(self.current()) {
54 break;
55 }
56
57 while matches!(self.current(), Token::Semi) {
58 self.advance();
59 self.skip_comments();
60 }
61
62 if terminators.contains(self.current()) || self.is_eof() {
63 break;
64 }
65
66 if matches!(
67 self.current(),
68 Token::Return | Token::Break | Token::Continue
69 ) {
70 statements.push(self.parse_statement()?);
71 while matches!(self.current(), Token::Semi) {
72 self.advance();
73 }
74
75 break;
76 }
77
78 statements.push(self.parse_statement()?);
79
80 if matches!(self.current(), Token::Semi) {
81 self.advance();
82 }
83 }
84
85 let end = self.current_span().end;
86 Ok(Block::new(statements, start..end))
87 }
88
89 pub(super) fn parse_parameters(&mut self) -> Result<Vec<Parameter>, ParseError> {
90 let mut parameters = Vec::new();
91 let mut seen_vararg = false;
92
93 while !matches!(self.current(), Token::RParen | Token::Eof) {
94 self.skip_comments();
95
96 if seen_vararg {
97 return Err(ParseError::InvalidSyntax {
98 message: "varargs (...) must be the last parameter".to_string(),
99 span: self.current_span(),
100 help: Some("move ... to the end of parameter list".to_string()),
101 });
102 }
103
104 if let Token::Dot3 = self.current() {
105 let span = self.current_span();
106 self.advance();
107
108 self.skip_type_annotation()?;
109
110 parameters.push(Parameter::vararg(span));
111 seen_vararg = true;
112
113 self.consume(Token::Comma);
114 continue;
115 }
116
117 let name = self.parse_identifier()?;
118
119 let attribute = if V::HAS_VARIABLE_ATTRIBUTES && matches!(self.current(), Token::Less) {
120 self.advance();
121 let attr = self.parse_identifier()?;
122 self.expect(Token::Greater)?;
123 Some(attr)
124 } else {
125 None
126 };
127
128 let type_annotation = if V::HAS_TYPE_ANNOTATIONS && matches!(self.current(), Token::Colon) {
129 Some(self.parse_type_annotation()?)
130 } else {
131 None
132 };
133
134 let span = name.span.clone();
135 parameters.push(Parameter::new(Some(name), attribute, type_annotation, false, span));
136
137 if !self.consume(Token::Comma) {
138 break;
139 }
140 }
141
142 Ok(parameters)
143 }
144
145 pub(super) fn parse_variable_name(&mut self) -> Result<VariableName, ParseError> {
146 let name = self.parse_identifier()?;
147
148 let attribute = if V::HAS_VARIABLE_ATTRIBUTES && matches!(self.current(), Token::Less) {
149 self.advance();
150 let attr = self.parse_identifier()?;
151 self.expect(Token::Greater)?;
152 Some(attr)
153 } else {
154 None
155 };
156
157 self.skip_type_annotation()?;
158
159 Ok(VariableName::new(name, attribute))
160 }
161
162 pub(super) fn parse_type_annotation(&mut self) -> Result<TypeAnnotation, ParseError> {
163 let start = self.current_span().start;
164 self.expect(Token::Colon)?;
165 self.skip_type_expression()?;
166 let end = self.current_span().end;
167 Ok(TypeAnnotation::new(start..end))
168 }
169
170 pub(super) fn skip_type_annotation(&mut self) -> Result<(), ParseError> {
171 if V::HAS_TYPE_ANNOTATIONS && matches!(self.current(), Token::Colon) {
172 self.advance();
173 self.skip_type_expression()?;
174 }
175 Ok(())
176 }
177
178 pub(super) fn skip_type_expression(&mut self) -> Result<(), ParseError> {
179 loop {
180 self.skip_type_primary()?;
181
182 while matches!(self.current(), Token::Question) {
183 self.advance();
184 }
185
186 match self.current() {
187 Token::Pipe | Token::Ampersand => {
188 self.advance();
189 continue;
190 }
191 _ => break,
192 }
193 }
194 Ok(())
195 }
196
197 fn skip_type_primary(&mut self) -> Result<(), ParseError> {
198 match self.current() {
199 Token::Identifier(name) if name == "typeof" => {
200 self.advance();
201 self.expect(Token::LParen)?;
202 let mut depth = 1;
205 while depth > 0 && !self.is_eof() {
206 match self.current() {
207 Token::LParen => {
208 depth += 1;
209 self.advance();
210 }
211 Token::RParen => {
212 depth -= 1;
213 if depth > 0 {
214 self.advance();
215 }
216 }
217 _ => {
218 self.advance();
219 }
220 }
221 }
222 self.expect(Token::RParen)?;
223 Ok(())
224 }
225 Token::Identifier(_) => {
226 self.advance();
227
228 while matches!(self.current(), Token::Dot) {
229 self.advance();
230 self.expect_identifier()?;
231 }
232
233 if matches!(self.current(), Token::Less) {
234 self.skip_generic_args()?;
235 }
236
237 Ok(())
238 }
239 Token::LBrace => {
240 self.advance();
241 self.skip_table_type()?;
242 self.expect(Token::RBrace)?;
243 Ok(())
244 }
245 Token::LParen => {
246 let checkpoint = self.checkpoint();
254 self.advance(); if matches!(self.current(), Token::RParen) {
258 self.advance(); if matches!(self.current(), Token::Arrow) {
261 self.advance(); self.skip_type_expression()?;
263 }
264 return Ok(());
265 }
266
267 let try_result = (|| -> Result<bool, ParseError> {
269 self.skip_function_type_params()?;
270 if !matches!(self.current(), Token::RParen) {
271 return Ok(false);
272 }
273 self.advance();
274 Ok(matches!(self.current(), Token::Arrow))
275 })();
276
277 match try_result {
278 Ok(true) => {
279 self.advance(); self.skip_type_expression()?;
282 }
283 _ => {
284 self.restore(checkpoint);
286 self.advance(); self.skip_type_expression()?;
289 while self.consume(Token::Comma) {
290 self.skip_type_expression()?;
291 }
292 self.expect(Token::RParen)?;
293 if matches!(self.current(), Token::Arrow) {
295 self.advance();
296 self.skip_type_expression()?;
297 }
298 }
299 }
300
301 Ok(())
302 }
303 Token::String(_) | Token::Number(_) | Token::True | Token::False | Token::Nil => {
304 self.advance();
305 Ok(())
306 }
307 Token::Less => {
308 self.skip_generic_args()?;
310 self.expect(Token::LParen)?;
311 self.skip_function_type_params()?;
312 self.expect(Token::RParen)?;
313 if matches!(self.current(), Token::Arrow) {
314 self.advance();
315 self.skip_type_expression()?;
316 }
317 Ok(())
318 }
319 Token::Dot3 => {
320 self.advance();
321 self.skip_type_expression()?;
322 Ok(())
323 }
324 _ => Err(ParseError::InvalidSyntax {
325 message: "expected type expression".to_string(),
326 span: self.current_span(),
327 help: None,
328 }),
329 }
330 }
331
332 pub fn skip_generic_args(&mut self) -> Result<(), ParseError> {
333 self.expect(Token::Less)?;
334
335 if matches!(self.current(), Token::Greater) {
336 self.advance();
337 return Ok(());
338 }
339
340 loop {
341 self.skip_type_expression()?;
342
343 match self.current() {
344 Token::Comma => {
345 self.advance();
346 continue;
347 }
348 Token::Greater => {
349 self.advance();
350 break;
351 }
352 Token::RightShift => {
353 self.split_right_shift();
355 self.advance(); break;
357 }
358 Token::GreaterEq => {
359 return Err(ParseError::InvalidSyntax {
360 message: "unexpected '>=' in generic arguments".to_string(),
361 span: self.current_span(),
362 help: Some("use '>' to close generic arguments".to_string()),
363 });
364 }
365 _ => {
366 return Err(ParseError::UnexpectedToken {
367 expected: vec![",".to_string(), ">".to_string()],
368 found: format!("{:?}", self.current()),
369 span: self.current_span(),
370 });
371 }
372 }
373 }
374
375 Ok(())
376 }
377
378 fn skip_table_type(&mut self) -> Result<(), ParseError> {
379 while !matches!(self.current(), Token::RBrace | Token::Eof) {
380 self.skip_comments();
381
382 if matches!(self.current(), Token::Comma | Token::Semi) {
383 self.advance();
384 continue;
385 }
386
387 if matches!(self.current(), Token::LBracket) {
388 self.advance();
389 self.skip_type_expression()?;
390 self.expect(Token::RBracket)?;
391 self.expect(Token::Colon)?;
392 self.skip_type_expression()?;
393 } else if let Token::Identifier(_) = self.current() {
394 self.advance();
395 if matches!(self.current(), Token::Colon) {
396 self.advance();
397 self.skip_type_expression()?;
398 }
399 } else {
400 break;
401 }
402 }
403
404 Ok(())
405 }
406
407 fn skip_function_type_params(&mut self) -> Result<(), ParseError> {
408 while !matches!(self.current(), Token::RParen | Token::Eof) {
409 self.skip_comments();
410
411 if matches!(self.current(), Token::Dot3) {
412 self.advance();
413 if matches!(self.current(), Token::Identifier(_)) {
414 self.advance();
415 }
416 if matches!(self.current(), Token::Colon) {
417 self.advance();
418 self.skip_type_expression()?;
419 }
420 break;
421 }
422
423 if matches!(self.current(), Token::Identifier(_)) {
424 self.advance();
425 if matches!(self.current(), Token::Colon) {
426 self.advance();
427 self.skip_type_expression()?;
428 }
429 } else {
430 self.skip_type_expression()?;
431 }
432
433 if !self.consume(Token::Comma) {
434 break;
435 }
436 }
437
438 Ok(())
439 }
440
441 fn expect_identifier(&mut self) -> Result<(), ParseError> {
442 if matches!(self.current(), Token::Identifier(_)) {
443 self.advance();
444 Ok(())
445 } else {
446 Err(ParseError::UnexpectedToken {
447 expected: vec!["identifier".to_string()],
448 found: format!("{:?}", self.current()),
449 span: self.current_span(),
450 })
451 }
452 }
453
454 pub(super) fn parse_attributes(&mut self) -> Result<Vec<Attribute>, ParseError> {
455 let mut attributes = Vec::new();
456
457 while matches!(self.current(), Token::At) {
458 self.advance();
459
460 let name = self.parse_identifier()?;
461 let fields = if matches!(self.current(), Token::LBracket) {
462 self.advance();
463 let fields = self.parse_attribute_fields()?;
464 self.expect(Token::RBracket)?;
465 Some(fields)
466 } else {
467 None
468 };
469
470 let span = name.span.clone();
471 attributes.push(Attribute::new(name, fields, span));
472 }
473
474 Ok(attributes)
475 }
476
477 fn parse_attribute_fields(&mut self) -> Result<Vec<AttributeField>, ParseError> {
478 let mut fields = Vec::new();
479
480 while !matches!(self.current(), Token::RBracket | Token::Eof) {
481 self.skip_comments();
482
483 if matches!(self.current(), Token::Comma) {
484 self.advance();
485 continue;
486 }
487
488 let checkpoint = self.checkpoint();
489 let key = if let Ok(ident) = self.parse_identifier() {
490 if matches!(self.current(), Token::Eq) {
491 self.advance();
492 Some(ident)
493 } else {
494 self.restore(checkpoint);
495 None
496 }
497 } else {
498 None
499 };
500
501 let value = self.parse_attribute_value()?;
502 fields.push(AttributeField::new(key, value));
503
504 if !self.consume(Token::Comma) {
505 break;
506 }
507 }
508
509 Ok(fields)
510 }
511
512 fn parse_attribute_value(&mut self) -> Result<AttributeValue, ParseError> {
513 match self.current() {
514 Token::String(s) => {
515 let s = s.clone();
516 self.advance();
517 Ok(AttributeValue::String(s))
518 }
519 Token::Number(n) => {
520 let n = n.clone();
521 self.advance();
522 Ok(AttributeValue::Number(n))
523 }
524 Token::True => {
525 self.advance();
526 Ok(AttributeValue::Boolean(true))
527 }
528 Token::False => {
529 self.advance();
530 Ok(AttributeValue::Boolean(false))
531 }
532 Token::Identifier(_) => {
533 let ident = self.parse_identifier()?;
534 Ok(AttributeValue::Identifier(ident))
535 }
536 _ => Err(ParseError::UnexpectedToken {
537 expected: vec!["string, number, boolean, or identifier".to_string()],
538 found: format!("{:?}", self.current()),
539 span: self.current_span(),
540 }),
541 }
542 }
543}