1use crate::ast::*;
2use crate::tokens::{Token, TokenType, TokenValue};
3use rslua_derive::Traceable;
4use rslua_traits::Error;
5
6#[derive(Traceable, Default)]
7pub struct Parser {
8 tokens: Vec<Token>,
9 current: usize,
10}
11
12#[derive(Debug)]
13pub struct SyntaxError(String);
14
15impl Error for SyntaxError {
16 fn what(&self) -> &str {
17 &self.0
18 }
19}
20
21type ParseResult<T> = Result<T, SyntaxError>;
22
23impl Parser {
24
25 pub fn run(&mut self, tokens: Vec<Token>) -> ParseResult<Block> {
26 self.reset();
27 self.tokens = tokens;
28 self.block()
29 }
30
31 fn block(&mut self) -> ParseResult<Block> {
33 let mut stats: Vec<Stat> = Vec::new();
34 while !self.is_block_end() {
35 let stat = self.stat()?;
36 if let Some(stat) = stat {
37 let should_break = matches!(stat, Stat::RetStat(_));
38 stats.push(stat);
39 if should_break {
40 break;
41 }
42 }
43 }
44 Ok(Block { stats })
45 }
46
47 fn stat(&mut self) -> ParseResult<Option<Stat>> {
48 let stat = match self.current_token_type() {
49 TokenType::Semi | TokenType::SComment | TokenType::MComment => {
51 self.next();
52 return Ok(None);
53 }
54 TokenType::If => Stat::IfStat(self.ifstat()?),
56 TokenType::While => Stat::WhileStat(self.whilestat()?),
58 TokenType::Do => Stat::DoBlock(self.doblock()?),
60 TokenType::For => Stat::ForStat(self.forstat()?),
62 TokenType::Repeat => Stat::RepeatStat(self.repeatstat()?),
64 TokenType::Function => Stat::FuncStat(self.funcstat()?),
66 TokenType::Local => {
68 let local = self.next_and_skip_comment();
69 if self.test(TokenType::Function) {
70 Stat::FuncStat(self.localfunc(local)?)
71 } else {
72 Stat::LocalStat(self.localstat(local)?)
73 }
74 }
75 TokenType::DbColon => Stat::LabelStat(self.labelstat()?),
77 TokenType::Return => Stat::RetStat(self.retstat()?),
79 TokenType::Break => Stat::BreakStat(self.breakstat()?),
81 TokenType::Goto => Stat::GotoStat(self.gotostat()?),
83 _ => self.exprstat()?,
85 };
86 Ok(Some(stat))
87 }
88
89 fn doblock(&mut self) -> ParseResult<DoBlock> {
90 let line = self.current_line();
91 let do_ = self.next();
92 let block = self.block()?;
93 let end = self.check_match(TokenType::End, TokenType::Do, line)?;
94 Ok(DoBlock { do_, block, end })
95 }
96
97 fn ifstat(&mut self) -> ParseResult<IfStat> {
99 let line = self.current_line();
100 let mut cond_blocks: Vec<CondBlock> = Vec::new();
101 cond_blocks.push(self.test_then_block()?);
102 while self.current_token_type() == TokenType::ElseIf {
103 cond_blocks.push(self.test_then_block()?);
104 }
105 let mut else_ = None;
106 let mut else_block = None;
107 if let Some(else_token) = self.test_next(TokenType::Else) {
108 else_ = Some(else_token);
109 else_block = Some(self.block()?);
110 }
111 let end = self.check_match(TokenType::End, TokenType::If, line)?;
112 Ok(IfStat {
113 cond_blocks,
114 else_,
115 else_block,
116 end,
117 })
118 }
119
120 fn test_then_block(&mut self) -> ParseResult<CondBlock> {
122 let if_ = self.next_and_skip_comment();
123 let cond = self.cond()?;
124 let then = self.check_next(TokenType::Then)?;
125 let block = self.block()?;
126 Ok(CondBlock {
127 if_,
128 cond,
129 then,
130 block,
131 })
132 }
133
134 fn whilestat(&mut self) -> ParseResult<WhileStat> {
136 let line = self.current_line();
137 let while_ = self.next_and_skip_comment();
138 let cond = self.cond()?;
139 let do_ = self.check_next(TokenType::Do)?;
140 let block = self.block()?;
141 let end = self.check_match(TokenType::End, TokenType::While, line)?;
142 Ok(WhileStat {
143 while_,
144 cond,
145 do_,
146 block,
147 end,
148 })
149 }
150
151 fn cond(&mut self) -> ParseResult<Expr> {
152 self.expr()
153 }
154
155 fn forstat(&mut self) -> ParseResult<ForStat> {
157 let line = self.current_line();
158 let for_ = self.next_and_skip_comment();
159 let var = self.check_name()?;
160 match self.current_token_type() {
161 TokenType::Assign => self.forenum(line, for_, var),
162 TokenType::Comma | TokenType::In => self.forlist(line, for_, var),
163 _ => self.syntax_error("'=' or 'in' expected"),
164 }
165 }
166
167 fn forenum(&mut self, line: usize, for_: Token, var: StringExpr) -> ParseResult<ForStat> {
169 let equal = self.next_and_skip_comment();
170 let init = self.expr()?;
171 let init_commas = self.check_next(TokenType::Comma)?;
172 self.skip_comment();
173 let limit = self.expr()?;
174 let limit_commas = self.test_next(TokenType::Comma);
175 let step = match limit_commas {
176 Some(_) => Some(self.expr()?),
177 None => None,
178 };
179 let do_ = self.check_next(TokenType::Do)?;
180 let body = self.block()?;
181 let end = self.check_match(TokenType::End, TokenType::For, line)?;
182 Ok(ForStat::ForNum(ForNum {
183 for_,
184 var,
185 equal,
186 init,
187 init_comma: init_commas,
188 limit,
189 limit_comma: limit_commas,
190 step,
191 do_,
192 body,
193 end,
194 }))
195 }
196
197 fn forlist(&mut self, line: usize, for_: Token, var: StringExpr) -> ParseResult<ForStat> {
199 let vars = self.varlist(TokenType::Comma, Some(var))?;
200 let in_ = self.check_next(TokenType::In)?;
201 self.skip_comment();
202 let exprs = self.exprlist()?;
203 let do_ = self.check_next(TokenType::Do)?;
204 let body = self.block()?;
205 let end = self.check_match(TokenType::End, TokenType::For, line)?;
206 Ok(ForStat::ForList(ForList {
207 for_,
208 vars,
209 in_,
210 exprs,
211 do_,
212 body,
213 end,
214 }))
215 }
216
217 fn varlist(
218 &mut self,
219 delimiter: TokenType,
220 first_var: Option<StringExpr>,
221 ) -> ParseResult<VarList> {
222 let mut vars = VarList {
223 vars: Vec::new(),
224 delimiters: Vec::new(),
225 };
226 let var = match first_var {
227 Some(var) => var,
228 None => self.check_name()?,
229 };
230 vars.vars.push(var);
231 while let Some(comma) = self.test_next(delimiter) {
232 vars.delimiters.push(comma);
233 vars.vars.push(self.check_name()?);
234 }
235 Ok(vars)
236 }
237
238 fn repeatstat(&mut self) -> ParseResult<RepeatStat> {
240 let line = self.current_line();
241 let repeat = self.next();
242 let block = self.block()?;
243 let until = self.check_match(TokenType::Until, TokenType::Repeat, line)?;
244 let cond = self.cond()?;
245 Ok(RepeatStat {
246 repeat,
247 block,
248 until,
249 cond,
250 })
251 }
252
253 fn funcstat(&mut self) -> ParseResult<FuncStat> {
255 let function = self.next_and_skip_comment();
256 let func_name = self.funcname()?;
257 let body = self.funcbody()?;
258 Ok(FuncStat {
259 function,
260 func_type: FuncType::Global,
261 func_name,
262 body,
263 })
264 }
265
266 fn funcname(&mut self) -> ParseResult<FuncName> {
268 let fields = self.varlist(TokenType::Attr, None)?;
269 let mut method = None;
270 if let Some(colon) = self.test_next(TokenType::Colon) {
271 method = Some((colon, self.check_name()?));
272 }
273 Ok(FuncName { fields, method })
274 }
275
276 fn funcbody(&mut self) -> ParseResult<FuncBody> {
278 let line = self.current_line();
279 let lp = self.check_next(TokenType::Lp)?;
280 self.skip_comment();
281 let mut params = ParamList {
282 params: Vec::new(),
283 commas: Vec::new(),
284 };
285 loop {
286 if self.test(TokenType::Rp) {
287 break;
288 }
289 match self.current_token_type() {
290 TokenType::Dots => {
291 params.params.push(Param::VarArg(self.current_token()));
292 self.next_and_skip_comment();
293 }
294 TokenType::Name => params.params.push(Param::Name(self.check_name()?)),
295 _ => self.syntax_error("<name> or '...' expected")?,
296 };
297 self.skip_comment();
298 if let Some(commas) = self.test_next(TokenType::Comma) {
299 params.commas.push(commas);
300 self.skip_comment();
301 } else {
302 break;
303 }
304 }
305 let rp = self.check_next(TokenType::Rp)?;
306 let block = self.block()?;
307 let end = self.check_match(TokenType::End, TokenType::Function, line)?;
308 Ok(FuncBody {
309 lp,
310 params,
311 rp,
312 block,
313 end,
314 })
315 }
316
317 fn localfunc(&mut self, token: Token) -> ParseResult<FuncStat> {
319 let function = self.current_token();
320 self.next_and_skip_comment();
321 let func_name = self.funcname()?;
322 let body = self.funcbody()?;
323 Ok(FuncStat {
324 func_type: FuncType::Local(token),
325 function,
326 func_name,
327 body,
328 })
329 }
330
331 fn localstat(&mut self, local: Token) -> ParseResult<LocalStat> {
333 let names = self.varlist(TokenType::Comma, None)?;
334 let equal = self.test_next(TokenType::Assign);
335 let exprs = if equal.is_some() {
336 Some(self.exprlist()?)
337 } else {
338 None
339 };
340 Ok(LocalStat {
341 local,
342 names,
343 equal,
344 exprs,
345 })
346 }
347
348 fn labelstat(&mut self) -> ParseResult<LabelStat> {
350 let ldc = self.next();
351 self.skip_comment();
352 let label = self.check_name()?;
353 let rdc = self.check_next(TokenType::DbColon)?;
354 self.skip_comment();
355 Ok(LabelStat { ldc, label, rdc })
356 }
357
358 fn retstat(&mut self) -> ParseResult<RetStat> {
360 let return_ = self.next_and_skip_comment();
361 let exprs = if !self.is_block_end() && self.current_token_type() != TokenType::Semi {
362 Some(self.exprlist()?)
363 } else {
364 None
365 };
366 let semi = self.test_next(TokenType::Semi);
367 Ok(RetStat {
368 return_,
369 exprs,
370 semi,
371 })
372 }
373
374 fn breakstat(&mut self) -> ParseResult<BreakStat> {
375 let token = self.next_and_skip_comment();
376 Ok(BreakStat { token })
377 }
378
379 fn gotostat(&mut self) -> ParseResult<GotoStat> {
380 let goto = self.next_and_skip_comment();
381 let label = self.check_name()?;
382 Ok(GotoStat { goto, label })
383 }
384
385 fn exprstat(&mut self) -> ParseResult<Stat> {
387 let expr = self.suffixedexpr()?;
388 if self.test(TokenType::Assign) || self.test(TokenType::Comma) {
389 Ok(Stat::AssignStat(self.assignment(expr.to_assignable())?))
390 } else {
391 Ok(Stat::CallStat(CallStat {
392 call: expr.to_assignable(),
393 }))
394 }
395 }
396
397 fn assignment(&mut self, first: Assignable) -> ParseResult<AssignStat> {
400 let mut left = AssignableList {
401 assignables: Vec::new(),
402 commas: Vec::new(),
403 };
404 left.assignables.push(first);
405 while let Some(comma) = self.test_next(TokenType::Comma) {
406 left.commas.push(comma);
407 left.assignables.push(self.suffixedexpr()?.to_assignable())
408 }
409 let equal = self.check_next(TokenType::Assign)?;
410 self.skip_comment();
411 let right = self.exprlist()?;
412 Ok(AssignStat { left, equal, right })
413 }
414
415 fn exprlist(&mut self) -> ParseResult<ExprList> {
417 let mut exprs = ExprList::default();
418 self.skip_comment();
419 exprs.exprs.push(self.expr()?);
420 while let Some(comma) = self.test_next(TokenType::Comma) {
421 exprs.commas.push(comma);
422 self.skip_comment();
423 exprs.exprs.push(self.expr()?)
424 }
425 self.skip_comment();
426 Ok(exprs)
427 }
428
429 fn expr(&mut self) -> ParseResult<Expr> {
430 self.subexpr(0)
431 }
432
433 fn get_unop(&self) -> UnOp {
434 UnOp::from_token(self.current_token())
435 }
436
437 fn get_binop(&self) -> BinOp {
438 BinOp::from_token(self.current_token())
439 }
440
441 fn subexpr(&mut self, limit: u8) -> ParseResult<Expr> {
444 let mut left;
445 let unop = self.get_unop();
446 if unop != UnOp::None {
447 self.next_and_skip_comment();
448 let expr = Box::new(self.subexpr(unop.priority())?);
449 left = Expr::UnExpr(UnExpr {
450 op: unop.clone(),
451 expr,
452 });
453 } else {
454 left = self.simpleexpr()?;
455 }
456 let mut binop = self.get_binop();
457 while binop != BinOp::None && binop.priority().left > limit {
458 self.next_and_skip_comment();
459 let right = self.subexpr(binop.priority().right)?;
460 left = Expr::BinExpr(BinExpr {
461 left: Box::new(left),
462 right: Box::new(right),
463 op: binop,
464 });
465 binop = self.get_binop();
466 }
467 Ok(left)
468 }
469
470 fn simpleexpr(&mut self) -> ParseResult<Expr> {
472 let token = self.current_token();
473 let expr = match token.t {
474 TokenType::Flt => Expr::Float(FloatExpr { token }),
475 TokenType::Int => Expr::Int(IntExpr { token }),
476 TokenType::String => Expr::String(StringExpr { token }),
477 TokenType::Nil => Expr::Nil(token),
478 TokenType::True => Expr::True(token),
479 TokenType::False => Expr::False(token),
480 TokenType::Dots => Expr::VarArg(token),
481 TokenType::Lb => return Ok(Expr::Table(self.table()?)),
482 TokenType::Function => {
483 self.next_and_skip_comment();
484 return Ok(Expr::FuncBody(self.funcbody()?));
485 }
486 _ => return self.suffixedexpr(),
487 };
488 self.next_and_skip_comment();
489 Ok(expr)
490 }
491
492 fn suffixedexpr(&mut self) -> ParseResult<Expr> {
494 let primary = self.primaryexpr()?;
495 let mut suffixes: Vec<Suffix> = Vec::new();
496 loop {
497 match self.current_token_type() {
498 TokenType::Attr => {
499 let attr = self.next_and_skip_comment();
500 suffixes.push(Suffix::Attr(attr, self.check_name()?));
501 }
502 TokenType::Ls => {
503 let line = self.current_line();
504 let ls = self.next_and_skip_comment();
505 suffixes.push(Suffix::Index(
506 ls,
507 self.expr()?,
508 self.check_match(TokenType::Rs, TokenType::Ls, line)?,
509 ));
510 }
511 TokenType::Colon => {
512 let colon = self.next_and_skip_comment();
513 let name = self.check_name()?;
514 suffixes.push(Suffix::Method(colon, name));
515 }
516 TokenType::Lp | TokenType::Lb | TokenType::String => {
517 suffixes.push(Suffix::FuncArgs(self.funcargs()?));
518 }
519 _ => break,
520 }
521 }
522
523 if suffixes.is_empty() {
524 Ok(primary)
525 } else {
526 Ok(Expr::SuffixedExpr(SuffixedExpr {
527 primary: Box::new(primary),
528 suffixes,
529 }))
530 }
531 }
532
533 fn primaryexpr(&mut self) -> ParseResult<Expr> {
535 let expr = match self.current_token_type() {
536 TokenType::Name => Expr::Name(self.check_name()?),
537 TokenType::Lp => {
538 let line = self.current_line();
539 self.next_and_skip_comment();
540 let expr = self.expr()?;
541 self.check_match(TokenType::Rp, TokenType::Lp, line)?;
542 Expr::ParenExpr(Box::new(expr))
543 }
544 _ => {
545 return self.syntax_error(&format!(
546 "unexpected symbol '{:?}'",
547 self.current_token_type()
548 ))
549 }
550 };
551 Ok(expr)
552 }
553
554 fn table(&mut self) -> ParseResult<Table> {
557 let line = self.current_line();
558 let lb = self.check_next(TokenType::Lb)?;
559 self.skip_comment();
560 let mut fields: Vec<Field> = Vec::new();
561 while !self.test(TokenType::Rb) {
562 fields.push(self.field()?);
563 }
564 let rb = self.check_match(TokenType::Rb, TokenType::Lb, line)?;
565 Ok(Table { lb, fields, rb })
566 }
567
568 fn field(&mut self) -> ParseResult<Field> {
570 let field = match self.current_token_type() {
571 TokenType::Name => {
572 if self.next_token_type() == TokenType::Assign {
573 self.recfield()?
574 } else {
575 self.listfield()?
576 }
577 }
578 TokenType::Ls => self.recfield()?,
579 _ => self.listfield()?,
580 };
581 self.skip_comment();
582 Ok(field)
583 }
584
585 fn recfield(&mut self) -> ParseResult<Field> {
587 let key = match self.current_token_type() {
588 TokenType::Name => FieldKey::Name(self.check_name()?),
589 TokenType::Ls => {
590 let line = self.current_line();
591 let ls = self.next_and_skip_comment();
592 let expr = self.expr()?;
593 let rs = self.check_match(TokenType::Rs, TokenType::Ls, line)?;
594 FieldKey::Expr(ls, expr, rs)
595 }
596 _ => unreachable!(),
597 };
598 let equal = self.check_next(TokenType::Assign)?;
599 self.skip_comment();
600 let value = self.expr()?;
601 self.skip_comment();
602 let sep = self
603 .test_next(TokenType::Comma)
604 .or_else(|| self.test_next(TokenType::Semi));
605 Ok(Field::RecField(RecField {
606 key,
607 equal,
608 value,
609 sep,
610 }))
611 }
612
613 fn listfield(&mut self) -> ParseResult<Field> {
615 let expr = self.expr()?;
616 let sep = self
617 .test_next(TokenType::Comma)
618 .or_else(|| self.test_next(TokenType::Semi));
619 Ok(Field::ListField(ListField { value: expr, sep }))
620 }
621
622 fn funcargs(&mut self) -> ParseResult<FuncArgs> {
624 let func_args = match self.current_token_type() {
625 TokenType::Lp => {
626 let line = self.current_line();
627 let lp = self.next_and_skip_comment();
628
629 if let Some(rp) = self.test_next(TokenType::Rp) {
631 return Ok(FuncArgs::Exprs(lp, ExprList::default(), rp));
632 }
633
634 let exprs = self.exprlist()?;
635 let rp = self.check_match(TokenType::Rp, TokenType::Lp, line)?;
636 FuncArgs::Exprs(lp, exprs, rp)
637 }
638 TokenType::Lb => FuncArgs::Table(self.table()?),
639 TokenType::String => FuncArgs::String(StringExpr {
640 token: self.next_and_skip_comment(),
641 }),
642 _ => return self.syntax_error("function arguments expected"),
643 };
644 Ok(func_args)
645 }
646
647 fn reset(&mut self) {
648 self.current = 0;
649 }
650
651 fn current_token(&self) -> Token {
652 self.tokens[self.current].clone()
653 }
654
655 fn next_token(&self) -> &Token {
656 let mut current = self.current + 1;
657 while self.tokens[current].is_comment() {
658 current += 1;
659 }
660 &self.tokens[current]
661 }
662
663 fn current_token_type(&self) -> TokenType {
664 let token = self.current_token();
665 token.t
666 }
667
668 fn current_line(&self) -> usize {
669 let token = self.current_token();
670 token.source.line
671 }
672
673 fn next_token_type(&self) -> TokenType {
674 let token = self.next_token();
675 token.t
676 }
677
678 fn next_and_skip_comment(&mut self) -> Token {
679 let token = self.current_token();
680 self.current += 1;
681 self.skip_comment();
682 token
683 }
684
685 fn next(&mut self) -> Token {
686 let token = self.current_token();
687 self.current += 1;
688 token
689 }
690
691 fn skip_comment(&mut self) -> usize {
692 let old = self.current;
693 while self.current_token().is_comment() {
694 self.current += 1;
695 }
696 old
697 }
698
699 fn is_block_end(&self) -> bool {
701 let token = self.current_token();
702 matches!(token.t, TokenType::Else
703 | TokenType::ElseIf
704 | TokenType::End
705 | TokenType::Until
706 | TokenType::Eos)
707 }
708
709 fn check_match(&mut self, end: TokenType, start: TokenType, line: usize) -> ParseResult<Token> {
710 self.skip_comment();
711 if self.current_token_type() != end {
712 if line == self.current_line() {
713 self.error_expected(end)?;
714 } else {
715 self.syntax_error(&format!(
716 "{:?} expected (to close {:?} at line {})",
717 end, start, line
718 ))?;
719 }
720 }
721 Ok(self.next())
722 }
723
724 fn test(&self, expected: TokenType) -> bool {
725 self.current_token_type() == expected
726 }
727
728 fn test_next(&mut self, expected: TokenType) -> Option<Token> {
729 let origin = self.skip_comment();
730 if self.test(expected) {
731 Some(self.next())
732 } else {
733 self.current = origin;
734 None
735 }
736 }
737
738 fn check(&self, expected: TokenType) -> ParseResult<Token> {
739 if self.current_token_type() != expected {
740 self.error_expected(expected)
741 } else {
742 Ok(self.current_token())
743 }
744 }
745
746 fn check_next(&mut self, expected: TokenType) -> ParseResult<Token> {
747 self.skip_comment();
748 self.check(expected)?;
749 Ok(self.next())
750 }
751
752 fn check_name(&mut self) -> ParseResult<StringExpr> {
753 self.skip_comment();
754 self.check(TokenType::Name)?;
755 Ok(StringExpr { token: self.next() })
756 }
757
758 fn syntax_error<T>(&self, msg: &str) -> ParseResult<T> {
759 let token = self.current_token();
760 let ident = match token.value {
761 TokenValue::None => format!("{:?}", token.t),
762 _ => format!("{:?}", token.value),
763 };
764 let error_msg = format!(
765 "[syntax error] {} at line [{}:{}] near [{}]",
766 msg, token.source.line, token.source.col, ident
767 );
768 Parser::trace_error(SyntaxError(error_msg))
769 }
770
771 fn error_expected<T>(&self, expected: TokenType) -> ParseResult<T> {
772 self.syntax_error(&format!("{:?} expected", expected))
773 }
774}