1use crate::frontend::ast::*;
6use crate::frontend::error::SyntaxError;
7use crate::frontend::goto_check::GotoCheck;
8use crate::frontend::lexer::{Lexed, Lexer};
9use crate::frontend::span::Span;
10use crate::frontend::token::{Near, Token, TokenInfo, near_text};
11use crate::version::LuaVersion;
12
13const MAX_DEPTH: u32 = 200;
19
20const MAXVARS: u32 = 200;
22
23type DeclList = (Option<Attrib>, Vec<AttribName>, Vec<ExprId>);
25
26fn bin_priority(op: BinOp) -> (u8, u8) {
29 match op {
30 BinOp::Or => (1, 1),
31 BinOp::And => (2, 2),
32 BinOp::Lt | BinOp::Gt | BinOp::Le | BinOp::Ge | BinOp::Ne | BinOp::Eq => (3, 3),
33 BinOp::BOr => (4, 4),
34 BinOp::BXor => (5, 5),
35 BinOp::BAnd => (6, 6),
36 BinOp::Shl | BinOp::Shr => (7, 7),
37 BinOp::Concat => (9, 8),
38 BinOp::Add | BinOp::Sub => (10, 10),
39 BinOp::Mul | BinOp::Div | BinOp::IDiv | BinOp::Mod => (11, 11),
40 BinOp::Pow => (14, 13),
41 }
42}
43
44const UNARY_PRIORITY: u8 = 12;
45
46fn bin_op_of(tok: &Token) -> Option<BinOp> {
47 Some(match tok {
48 Token::Plus => BinOp::Add,
49 Token::Minus => BinOp::Sub,
50 Token::Star => BinOp::Mul,
51 Token::Slash => BinOp::Div,
52 Token::DSlash => BinOp::IDiv,
53 Token::Percent => BinOp::Mod,
54 Token::Caret => BinOp::Pow,
55 Token::Concat => BinOp::Concat,
56 Token::Eq => BinOp::Eq,
57 Token::Ne => BinOp::Ne,
58 Token::Lt => BinOp::Lt,
59 Token::Le => BinOp::Le,
60 Token::Gt => BinOp::Gt,
61 Token::Ge => BinOp::Ge,
62 Token::And => BinOp::And,
63 Token::Or => BinOp::Or,
64 Token::Amp => BinOp::BAnd,
65 Token::Pipe => BinOp::BOr,
66 Token::Tilde => BinOp::BXor,
67 Token::Shl => BinOp::Shl,
68 Token::Shr => BinOp::Shr,
69 _ => return None,
70 })
71}
72
73fn un_op_of(tok: &Token) -> Option<UnOp> {
74 Some(match tok {
75 Token::Minus => UnOp::Neg,
76 Token::Not => UnOp::Not,
77 Token::Hash => UnOp::Len,
78 Token::Tilde => UnOp::BNot,
79 _ => return None,
80 })
81}
82
83pub(crate) enum TokenSource<'s> {
89 Lexer(Lexer<'s>),
91 PreExpanded {
95 tokens: Vec<TokenInfo>,
96 cursor: usize,
97 src: &'s [u8],
98 },
99}
100
101struct Cur {
106 info: TokenInfo,
107 char: Option<u8>,
108}
109
110impl<'s> TokenSource<'s> {
111 fn next_token(&mut self) -> Result<Cur, SyntaxError> {
112 match self {
113 TokenSource::Lexer(l) => Ok(match l.next_lexed()? {
114 Lexed::Tok(info) => Cur { info, char: None },
115 Lexed::Char(c, mut info) => {
116 info.tok = Token::At;
117 Cur {
118 info,
119 char: Some(c),
120 }
121 }
122 }),
123 TokenSource::PreExpanded {
124 tokens,
125 cursor,
126 src,
127 } => {
128 if *cursor >= tokens.len() {
129 let line = tokens.last().map(|t| t.line).unwrap_or(1);
130 let _ = src;
131 Ok(Cur {
132 info: TokenInfo {
133 tok: Token::Eof,
134 span: Span::new(0, 0),
135 line,
136 },
137 char: None,
138 })
139 } else {
140 let t = tokens[*cursor].clone();
141 *cursor += 1;
142 Ok(Cur {
143 info: t,
144 char: None,
145 })
146 }
147 }
148 }
149 }
150
151 fn src(&self) -> &'s [u8] {
152 match self {
153 TokenSource::Lexer(l) => l.src(),
154 TokenSource::PreExpanded { src, .. } => src,
155 }
156 }
157
158 fn line(&self) -> u32 {
161 match self {
162 TokenSource::Lexer(l) => l.line(),
163 TokenSource::PreExpanded { tokens, cursor, .. } => tokens
164 .get(cursor.saturating_sub(1))
165 .or(tokens.last())
166 .map_or(1, |t| t.line),
167 }
168 }
169}
170
171pub fn parse(src: &[u8], version: LuaVersion) -> Result<Chunk, SyntaxError> {
180 parse_at_depth(src, version, 0).map(|p| p.chunk)
181}
182
183pub(crate) struct Parsed {
185 pub(crate) chunk: Chunk,
186 pub(crate) end_lines: Vec<u32>,
190}
191
192pub(crate) fn parse_at_depth(
197 src: &[u8],
198 version: LuaVersion,
199 c_depth: u32,
200) -> Result<Parsed, SyntaxError> {
201 let lex = Lexer::new(src, version);
202 parse_from_source(TokenSource::Lexer(lex), version, c_depth)
203}
204
205pub fn parse_tokens(
210 tokens: Vec<TokenInfo>,
211 src: &[u8],
212 version: LuaVersion,
213) -> Result<Chunk, SyntaxError> {
214 parse_tokens_at_depth(tokens, src, version, 0).map(|p| p.chunk)
215}
216
217pub(crate) fn parse_tokens_at_depth(
219 tokens: Vec<TokenInfo>,
220 src: &[u8],
221 version: LuaVersion,
222 c_depth: u32,
223) -> Result<Parsed, SyntaxError> {
224 parse_from_source(
225 TokenSource::PreExpanded {
226 tokens,
227 cursor: 0,
228 src,
229 },
230 version,
231 c_depth,
232 )
233}
234
235fn parse_from_source<'s>(
236 mut lex: TokenSource<'s>,
237 version: LuaVersion,
238 c_depth: u32,
239) -> Result<Parsed, SyntaxError> {
240 let cur = lex.next_token()?;
241 let mut p = Parser {
242 lex,
243 tok: cur.info,
244 tok_char: cur.char,
245 peeked: None,
246 prev_line: 1,
247 exprs: Vec::new(),
248 stats: Vec::new(),
249 stat_lines: Vec::new(),
250 end_lines: Vec::new(),
251 depth: c_depth,
252 version,
253 func_local_count: vec![(0, 0, 0)],
255 funcs: vec![FnFlow {
256 vararg: true,
257 loops: 0,
258 }],
259 gotos: GotoCheck::new(version),
260 last_line: 1,
261 upval_chain_51: if version <= LuaVersion::Lua51 {
262 vec![FnUvSlot {
263 line_defined: 0,
264 ..Default::default()
265 }]
266 } else {
267 Vec::new()
268 },
269 };
270 if let Some(g) = p.gotos.as_mut() {
271 g.enter_function();
272 }
273 let block = p.block()?;
274 if p.tok.tok != Token::Eof {
275 return Err(p.error_expected("<eof>"));
276 }
277 p.close_function()?;
278 let end_line = p.prev_line;
279 Ok(Parsed {
280 chunk: Chunk {
281 exprs: p.exprs,
282 stats: p.stats,
283 stat_lines: p.stat_lines,
284 block,
285 end_line,
286 },
287 end_lines: p.end_lines,
288 })
289}
290
291struct Parser<'s> {
292 lex: TokenSource<'s>,
293 tok: TokenInfo,
294 tok_char: Option<u8>,
296 peeked: Option<Cur>,
297 funcs: Vec<FnFlow>,
300 gotos: Option<GotoCheck>,
303 last_line: u32,
306 prev_line: u32,
308 exprs: Vec<Expr>,
309 stats: Vec<Stat>,
310 stat_lines: Vec<u32>,
313 end_lines: Vec<u32>,
315 depth: u32,
316 version: LuaVersion,
317 func_local_count: Vec<(u32, u32, u32)>,
325 upval_chain_51: Vec<FnUvSlot>,
336}
337
338struct FnFlow {
339 vararg: bool,
340 loops: u32,
342}
343
344#[derive(Default)]
345struct FnUvSlot {
346 locals: Vec<Box<str>>,
347 upvalues: std::collections::HashSet<Box<str>>,
348 line_defined: u32,
349}
350
351impl<'s> Parser<'s> {
352 fn advance(&mut self) -> Result<TokenInfo, SyntaxError> {
355 self.last_line = self.lex.line();
356 let next = match self.peeked.take() {
357 Some(t) => t,
358 None => self.lex.next_token()?,
359 };
360 self.prev_line = self.tok.line;
361 self.tok_char = next.char;
362 Ok(std::mem::replace(&mut self.tok, next.info))
363 }
364
365 fn peek(&mut self) -> Result<&Token, SyntaxError> {
366 if self.peeked.is_none() {
367 self.peeked = Some(self.lex.next_token()?);
368 }
369 Ok(&self.peeked.as_ref().unwrap().info.tok)
370 }
371
372 fn near(&self) -> Vec<u8> {
373 match self.tok_char {
374 Some(c) => near_text(self.version, Near::Char(c)),
375 None => self
376 .tok
377 .tok
378 .near_bytes(self.lex.src(), self.tok.span, self.version),
379 }
380 }
381
382 fn error(&self, msg: impl AsRef<str>) -> SyntaxError {
384 if self.tok_char == Some(0) {
387 return self.plain_error(msg.as_ref());
388 }
389 let mut bytes = msg.as_ref().as_bytes().to_vec();
390 bytes.extend_from_slice(b" near ");
391 bytes.extend_from_slice(&self.near());
392 SyntaxError {
393 line: self.lex.line(),
394 msg: bytes,
395 }
396 }
397
398 fn plain_error(&self, msg: impl Into<Vec<u8>>) -> SyntaxError {
400 SyntaxError {
401 line: self.lex.line(),
402 msg: msg.into(),
403 }
404 }
405
406 fn error_expected(&self, what: &str) -> SyntaxError {
409 if what.starts_with('<') && self.version >= LuaVersion::Lua52 {
410 self.error(format!("{what} expected"))
411 } else {
412 self.error(format!("'{what}' expected"))
413 }
414 }
415
416 fn accept(&mut self, tok: Token) -> Result<bool, SyntaxError> {
417 if self.tok.tok == tok {
418 self.advance()?;
419 Ok(true)
420 } else {
421 Ok(false)
422 }
423 }
424
425 fn expect(&mut self, tok: Token, what: &str) -> Result<(), SyntaxError> {
426 if !self.accept(tok)? {
427 return Err(self.error_expected(what));
428 }
429 Ok(())
430 }
431
432 fn expect_match(
434 &mut self,
435 tok: Token,
436 what: &str,
437 who: &str,
438 who_line: u32,
439 ) -> Result<(), SyntaxError> {
440 if !self.accept(tok)? {
441 if who_line == self.lex.line() {
442 return Err(self.error_expected(what));
443 }
444 return Err(self.error(format!(
445 "'{what}' expected (to close '{who}' at line {who_line})"
446 )));
447 }
448 Ok(())
449 }
450
451 fn expect_name(&mut self) -> Result<Name, SyntaxError> {
452 if !matches!(self.tok.tok, Token::Name(_)) {
453 return Err(self.error_expected("<name>"));
454 }
455 let info = self.advance()?;
456 let Token::Name(text) = info.tok else {
457 unreachable!()
458 };
459 Ok(Name {
460 text,
461 line: info.line,
462 })
463 }
464
465 fn enter(&mut self) -> Result<(), SyntaxError> {
466 self.depth += 1;
467 let limit = if self.version >= LuaVersion::Lua54 {
470 MAX_DEPTH - 1
471 } else {
472 MAX_DEPTH
473 };
474 if self.depth > limit {
475 return Err(self.levels_error());
476 }
477 Ok(())
478 }
479
480 fn levels_error(&self) -> SyntaxError {
486 match self.version {
487 LuaVersion::Lua51 => self.plain_error("chunk has too many syntax levels"),
488 LuaVersion::Lua52 | LuaVersion::Lua53 => self.error(format!(
489 "too many C levels (limit is 200) in {}",
490 self.where_()
491 )),
492 _ => SyntaxError::unpositioned("C stack overflow"),
493 }
494 }
495
496 fn where_(&self) -> String {
498 let &(_, line_defined, _) = self.func_local_count.last().expect("func ctx");
499 if self.func_local_count.len() == 1 {
500 "main function".to_string()
501 } else {
502 format!("function at line {line_defined}")
503 }
504 }
505
506 fn leave(&mut self) {
507 self.depth -= 1;
508 }
509
510 fn push_expr(&mut self, e: Expr) -> ExprId {
511 self.exprs.push(e);
512 ExprId((self.exprs.len() - 1) as u32)
513 }
514
515 fn push_stat(&mut self, s: Stat) -> StatId {
516 self.stats.push(s);
517 StatId((self.stats.len() - 1) as u32)
518 }
519
520 fn push_ended_stat(&mut self, s: Stat) -> StatId {
522 let id = self.push_stat(s);
523 let idx = id.0 as usize;
524 self.end_lines.resize(idx + 1, 0);
525 self.end_lines[idx] = self.prev_line;
526 id
527 }
528
529 fn block_follow(&self) -> bool {
532 matches!(
533 self.tok.tok,
534 Token::Eof | Token::End | Token::Else | Token::Elseif | Token::Until
535 )
536 }
537
538 fn block(&mut self) -> Result<Block, SyntaxError> {
539 self.enter()?;
540 let local_snapshot = self.func_local_count.last().expect("func ctx").0;
545 let locals_51_snap = self.snap_locals_51();
546 self.goto_step(|g| {
547 g.enter_block(false);
548 Ok(())
549 })?;
550 let mut stats = Vec::new();
551 loop {
552 if self.gotos.as_ref().is_some_and(GotoCheck::has_open_labels)
554 && !matches!(self.tok.tok, Token::Semi | Token::DColon)
555 {
556 let last = matches!(
557 self.tok.tok,
558 Token::Else | Token::Elseif | Token::End | Token::Eof
559 );
560 self.goto_step(|g| g.finish_labels(last))?;
561 }
562 if self.block_follow() {
563 break;
564 }
565 if self.tok.tok == Token::Return {
566 stats.push(self.return_stat()?);
567 break;
568 }
569 if self.tok.tok == Token::Break && self.version.break_is_last_statement() {
570 let line = self.tok.line;
571 self.break_stat()?;
572 stats.push(self.push_stat(Stat::Break { line }));
573 self.accept(Token::Semi)?;
574 break;
575 }
576 if let Some(s) = self.statement()? {
577 stats.push(s);
578 }
579 if !self.version.has_empty_statement() {
580 self.accept(Token::Semi)?;
582 }
583 }
584 self.goto_step(GotoCheck::leave_block)?;
585 self.leave();
586 self.func_local_count.last_mut().expect("func ctx").0 = local_snapshot;
587 self.restore_locals_51(locals_51_snap);
588 Ok(Block { stats })
589 }
590
591 fn return_stat(&mut self) -> Result<StatId, SyntaxError> {
592 let line = self.tok.line;
593 self.advance()?;
594 let exprs = if self.block_follow() || self.tok.tok == Token::Semi {
595 Vec::new()
596 } else {
597 self.exprlist()?
598 };
599 self.accept(Token::Semi)?;
600 Ok(self.push_stat(Stat::Return { exprs, line }))
601 }
602
603 fn statement(&mut self) -> Result<Option<StatId>, SyntaxError> {
604 let start_line = self.tok.line;
611 if self.version.has_global_decl()
616 && matches!(&self.tok.tok, Token::Name(n) if &**n == "global")
617 && matches!(
618 self.peek()?,
619 Token::Name(_) | Token::Star | Token::Function | Token::Lt
620 )
621 {
622 let stat = self.global_stat()?;
623 self.set_stat_line(stat, start_line);
624 return Ok(Some(stat));
625 }
626 let stat = match self.tok.tok {
627 Token::Semi => {
628 if !self.version.has_empty_statement() {
629 return Err(self.error("unexpected symbol"));
630 }
631 self.advance()?;
632 None
633 }
634 Token::If => Some(self.if_stat()?),
635 Token::While => Some(self.while_stat()?),
636 Token::Do => {
637 let line = self.tok.line;
638 self.advance()?;
639 let body = self.block()?;
640 self.expect_match(Token::End, "end", "do", line)?;
641 Some(self.push_stat(Stat::Do(body)))
642 }
643 Token::For => Some(self.for_stat()?),
644 Token::Repeat => Some(self.repeat_stat()?),
645 Token::Function => Some(self.function_stat()?),
646 Token::Local => Some(self.local_stat()?),
647 Token::DColon => {
648 self.advance()?;
649 let name = self.expect_name()?;
650 let text = name.text.clone();
651 self.goto_step(|g| g.label_before_close(&text, start_line))?;
652 self.expect(Token::DColon, "::")?;
653 Some(self.push_stat(Stat::Label(name)))
654 }
655 Token::Break => {
656 let line = self.tok.line;
657 self.break_stat()?;
658 Some(self.push_stat(Stat::Break { line }))
659 }
660 Token::Goto => {
661 let mut line = self.lex.line();
664 self.advance()?;
665 if self.version >= LuaVersion::Lua55 {
666 line = start_line;
667 } else if self.version >= LuaVersion::Lua54 {
668 line = self.lex.line();
669 }
670 let name = self.expect_name()?;
671 let text = name.text.clone();
672 self.goto_step(|g| g.goto_stat(&text, line))?;
673 Some(self.push_stat(Stat::Goto(name)))
674 }
675 _ => Some(self.expr_stat()?),
676 };
677 if let Some(sid) = stat {
678 self.set_stat_line(sid, start_line);
679 }
680 Ok(stat)
681 }
682
683 fn set_stat_line(&mut self, sid: StatId, line: u32) {
684 let idx = sid.0 as usize;
685 if self.stat_lines.len() <= idx {
686 self.stat_lines.resize(idx + 1, 0);
687 }
688 self.stat_lines[idx] = line;
689 }
690
691 fn break_stat(&mut self) -> Result<(), SyntaxError> {
696 let line = self.lex.line();
697 let in_loop = self.funcs.last().expect("func ctx").loops > 0;
698 if !in_loop && self.version >= LuaVersion::Lua55 {
699 return Err(self.error("break outside loop"));
700 }
701 self.advance()?;
702 if !in_loop && self.version <= LuaVersion::Lua51 {
703 return Err(self.error("no loop to break"));
704 }
705 if self.version >= LuaVersion::Lua55 {
706 return Ok(());
707 }
708 self.goto_step(|g| g.goto_stat("break", line))
709 }
710
711 fn loop_block(&mut self, vars: &[Name]) -> Result<Block, SyntaxError> {
715 self.funcs.last_mut().expect("func ctx").loops += 1;
716 self.goto_step(|g| {
717 g.enter_block(true);
718 g.enter_block(false);
719 for v in vars {
720 g.declare(&v.text);
721 }
722 Ok(())
723 })?;
724 let body = self.block()?;
725 self.goto_step(|g| {
726 g.leave_block()?;
727 g.leave_block()
728 })?;
729 self.funcs.last_mut().expect("func ctx").loops -= 1;
730 Ok(body)
731 }
732
733 fn close_function(&mut self) -> Result<(), SyntaxError> {
738 let _ = self.funcs.pop().expect("func ctx");
739 self.goto_step(GotoCheck::leave_block)
740 }
741
742 fn goto_step(
746 &mut self,
747 step: impl FnOnce(&mut GotoCheck) -> Result<(), String>,
748 ) -> Result<(), SyntaxError> {
749 match self.gotos.as_mut().map(step) {
750 Some(Err(msg)) if self.version >= LuaVersion::Lua55 => Err(SyntaxError {
751 line: self.last_line,
752 msg: msg.into_bytes(),
753 }),
754 Some(Err(msg)) => Err(self.plain_error(msg)),
755 _ => Ok(()),
756 }
757 }
758
759 fn if_stat(&mut self) -> Result<StatId, SyntaxError> {
760 let line = self.tok.line;
761 self.advance()?;
762 let mut arms = Vec::new();
763 let cond = self.expr()?;
764 let then_line = self.tok.line;
765 self.expect(Token::Then, "then")?;
766 arms.push((cond, then_line, self.block()?));
767 while self.tok.tok == Token::Elseif {
768 self.advance()?;
769 let cond = self.expr()?;
770 let then_line = self.tok.line;
771 self.expect(Token::Then, "then")?;
772 arms.push((cond, then_line, self.block()?));
773 }
774 let else_body = if self.accept(Token::Else)? {
775 Some(self.block()?)
776 } else {
777 None
778 };
779 self.expect_match(Token::End, "end", "if", line)?;
780 Ok(self.push_stat(Stat::If { arms, else_body }))
781 }
782
783 fn while_stat(&mut self) -> Result<StatId, SyntaxError> {
784 let line = self.tok.line;
785 self.advance()?;
786 let cond = self.expr()?;
787 self.expect(Token::Do, "do")?;
788 let body = self.loop_block(&[])?;
789 self.expect_match(Token::End, "end", "while", line)?;
790 Ok(self.push_ended_stat(Stat::While { cond, body }))
791 }
792
793 fn repeat_stat(&mut self) -> Result<StatId, SyntaxError> {
794 let line = self.tok.line;
795 self.advance()?;
796 let body = self.loop_block(&[])?;
797 self.expect_match(Token::Until, "until", "repeat", line)?;
798 let cond = self.expr()?;
799 Ok(self.push_stat(Stat::Repeat { body, cond }))
800 }
801
802 fn for_stat(&mut self) -> Result<StatId, SyntaxError> {
803 let line = self.tok.line;
804 self.advance()?;
805 let first = self.expect_name()?;
806 match self.tok.tok {
807 Token::Assign => {
808 self.advance()?;
809 let start = self.expr()?;
810 self.expect(Token::Comma, ",")?;
811 let limit = self.expr()?;
812 let step = if self.accept(Token::Comma)? {
813 Some(self.expr()?)
814 } else {
815 None
816 };
817 self.expect(Token::Do, "do")?;
818 self.add_local_51(&first.text);
819 let body = self.loop_block(std::slice::from_ref(&first))?;
820 self.expect_match(Token::End, "end", "for", line)?;
821 Ok(self.push_ended_stat(Stat::NumericFor {
822 var: first,
823 start,
824 limit,
825 step,
826 body,
827 }))
828 }
829 Token::Comma | Token::In => {
830 let mut vars = vec![first];
831 while self.accept(Token::Comma)? {
832 vars.push(self.expect_name()?);
833 }
834 self.expect(Token::In, "in")?;
835 let expr_line = self.tok.line;
836 let exprs = self.exprlist()?;
837 self.expect(Token::Do, "do")?;
838 for v in &vars {
839 self.add_local_51(&v.text);
840 }
841 let body = self.loop_block(&vars)?;
842 self.expect_match(Token::End, "end", "for", line)?;
843 Ok(self.push_ended_stat(Stat::GenericFor {
844 vars,
845 exprs,
846 body,
847 expr_line,
848 }))
849 }
850 _ => Err(self.error("'=' or 'in' expected")),
851 }
852 }
853
854 fn function_stat(&mut self) -> Result<StatId, SyntaxError> {
855 let line = self.tok.line;
856 self.advance()?;
857 let base = self.expect_name()?;
858 let mut path = Vec::new();
859 while self.accept(Token::Dot)? {
860 path.push(self.expect_name()?);
861 }
862 let method = if self.accept(Token::Colon)? {
863 Some(self.expect_name()?)
864 } else {
865 None
866 };
867 let body = self.func_body(line)?;
868 Ok(self.push_stat(Stat::Function {
869 name: FuncName { base, path, method },
870 body,
871 }))
872 }
873
874 fn attrib(&mut self) -> Result<Option<Attrib>, SyntaxError> {
875 if !(self.version.has_attribs() && self.tok.tok == Token::Lt) {
876 return Ok(None);
877 }
878 self.advance()?;
879 let name = self.expect_name()?;
880 let attrib = match &*name.text {
881 "const" => Attrib::Const,
882 "close" => Attrib::Close,
883 other => {
884 return Err(SyntaxError {
885 line: name.line,
886 msg: format!("unknown attribute '{other}'").into_bytes(),
887 });
888 }
889 };
890 self.expect(Token::Gt, ">")?;
891 Ok(Some(attrib))
892 }
893
894 fn attnamelist(&mut self) -> Result<DeclList, SyntaxError> {
897 let collective = if self.version.has_collective_attrib() {
898 self.attrib()?
899 } else {
900 None
901 };
902 let mut names = Vec::new();
903 loop {
904 let name = self.expect_name()?;
905 self.new_local()?;
906 let attrib = self.attrib()?;
907 names.push(AttribName { name, attrib });
908 if !self.accept(Token::Comma)? {
909 break;
910 }
911 }
912 let exprs = if self.accept(Token::Assign)? {
913 self.exprlist()?
914 } else {
915 Vec::new()
916 };
917 Ok((collective, names, exprs))
918 }
919
920 fn local_stat(&mut self) -> Result<StatId, SyntaxError> {
921 self.advance()?;
922 if self.accept(Token::Function)? {
923 let line = self.prev_line;
924 let name = self.expect_name()?;
925 self.new_local()?;
928 self.activate_locals()?;
929 self.add_local_51(&name.text);
930 let text = name.text.clone();
931 self.goto_step(|g| {
932 g.declare(&text);
933 Ok(())
934 })?;
935 let body = self.func_body(line)?;
936 return Ok(self.push_stat(Stat::LocalFunction { name, body }));
937 }
938 let (collective, names, exprs) = self.attnamelist()?;
939 self.activate_locals()?;
940 self.goto_step(|g| {
941 for an in &names {
942 g.declare(&an.name.text);
943 }
944 Ok(())
945 })?;
946 for an in &names {
947 self.add_local_51(&an.name.text);
948 }
949 Ok(self.push_stat(Stat::Local {
950 collective,
951 names,
952 exprs,
953 }))
954 }
955
956 fn global_stat(&mut self) -> Result<StatId, SyntaxError> {
957 self.advance()?;
958 if self.accept(Token::Function)? {
959 let line = self.prev_line;
960 let name = self.expect_name()?;
961 let text = name.text.clone();
962 self.goto_step(|g| {
963 g.declare(&text);
964 Ok(())
965 })?;
966 let body = self.func_body(line)?;
967 return Ok(self.push_stat(Stat::GlobalFunction { name, body }));
968 }
969 let leading = self.attrib()?;
971 if self.accept(Token::Star)? {
972 self.goto_step(|g| {
973 g.declare("*");
974 Ok(())
975 })?;
976 return Ok(self.push_stat(Stat::GlobalAll { attrib: leading }));
977 }
978 let mut names = Vec::new();
979 loop {
980 let name = self.expect_name()?;
981 let attrib = self.attrib()?;
982 names.push(AttribName { name, attrib });
983 if !self.accept(Token::Comma)? {
984 break;
985 }
986 }
987 let exprs = if self.accept(Token::Assign)? {
988 self.exprlist()?
989 } else {
990 Vec::new()
991 };
992 self.goto_step(|g| {
994 for an in &names {
995 g.declare(&an.name.text);
996 }
997 Ok(())
998 })?;
999 Ok(self.push_stat(Stat::Global {
1000 collective: leading,
1001 names,
1002 exprs,
1003 }))
1004 }
1005
1006 fn expr_stat(&mut self) -> Result<StatId, SyntaxError> {
1007 let first = self.suffixed_expr()?;
1008 let is_call = matches!(
1009 self.exprs[first.0 as usize],
1010 Expr::Call { .. } | Expr::MethodCall { .. }
1011 );
1012 let assign = if self.version <= LuaVersion::Lua51 {
1016 !is_call
1017 } else {
1018 matches!(self.tok.tok, Token::Assign | Token::Comma)
1019 };
1020 if !assign {
1021 if !is_call {
1022 return Err(self.error("syntax error"));
1023 }
1024 return Ok(self.push_stat(Stat::Call(first)));
1025 }
1026 let mut targets = vec![first];
1029 let mut entered = 0;
1030 loop {
1031 let last = *targets.last().expect("one target");
1032 if !matches!(
1033 self.exprs[last.0 as usize],
1034 Expr::Name(_) | Expr::Index { .. }
1035 ) {
1036 return Err(self.error("syntax error"));
1037 }
1038 if !self.accept(Token::Comma)? {
1039 break;
1040 }
1041 let nvars = targets.len() as u32;
1047 targets.push(self.suffixed_expr()?);
1048 match self.version {
1049 LuaVersion::Lua51 => {
1050 let limit = MAX_DEPTH.saturating_sub(self.depth);
1051 if nvars > limit {
1052 return Err(self.plain_error(format!(
1053 "{} has more than {limit} variables in assignment",
1054 self.where_()
1055 )));
1056 }
1057 }
1058 LuaVersion::Lua52 | LuaVersion::Lua53 => {
1059 if nvars + self.depth > MAX_DEPTH {
1060 return Err(self.levels_error());
1061 }
1062 }
1063 _ => {
1064 self.enter()?;
1065 entered += 1;
1066 }
1067 }
1068 }
1069 self.expect(Token::Assign, "=")?;
1070 let exprs = self.exprlist()?;
1071 self.depth -= entered;
1072 Ok(self.push_stat(Stat::Assign { targets, exprs }))
1073 }
1074
1075 fn exprlist(&mut self) -> Result<Vec<ExprId>, SyntaxError> {
1078 let mut list = vec![self.expr()?];
1079 while self.accept(Token::Comma)? {
1080 list.push(self.expr()?);
1081 }
1082 Ok(list)
1083 }
1084
1085 fn expr(&mut self) -> Result<ExprId, SyntaxError> {
1086 self.sub_expr(0)
1087 }
1088
1089 fn sub_expr(&mut self, limit: u8) -> Result<ExprId, SyntaxError> {
1090 self.enter()?;
1091 let mut left = if let Some(op) = un_op_of(&self.tok.tok) {
1092 let line = self.tok.line;
1093 self.advance()?;
1094 let operand = self.sub_expr(UNARY_PRIORITY)?;
1095 self.push_expr(Expr::UnOp { op, operand, line })
1096 } else {
1097 self.simple_expr()?
1098 };
1099 while let Some(op) = bin_op_of(&self.tok.tok) {
1100 let (lp, rp) = bin_priority(op);
1101 if lp <= limit {
1102 break;
1103 }
1104 let line = self.tok.line;
1105 self.advance()?;
1106 let rhs = self.sub_expr(rp)?;
1107 left = self.push_expr(Expr::BinOp {
1108 op,
1109 lhs: left,
1110 rhs,
1111 line,
1112 });
1113 }
1114 self.leave();
1115 Ok(left)
1116 }
1117
1118 fn simple_expr(&mut self) -> Result<ExprId, SyntaxError> {
1119 let e = match &self.tok.tok {
1120 Token::Nil => {
1121 self.advance()?;
1122 Expr::Nil
1123 }
1124 Token::True => {
1125 self.advance()?;
1126 Expr::True
1127 }
1128 Token::False => {
1129 self.advance()?;
1130 Expr::False
1131 }
1132 Token::Ellipsis => {
1133 if !self.funcs.last().expect("func ctx").vararg {
1134 return Err(self.error("cannot use '...' outside a vararg function"));
1135 }
1136 self.advance()?;
1137 Expr::Vararg
1138 }
1139 Token::Int(_) => {
1140 let Token::Int(v) = self.advance()?.tok else {
1141 unreachable!()
1142 };
1143 Expr::Int(v)
1144 }
1145 Token::Float(_) => {
1146 let Token::Float(v) = self.advance()?.tok else {
1147 unreachable!()
1148 };
1149 Expr::Float(v)
1150 }
1151 Token::Str(_) => {
1152 let Token::Str(s) = self.advance()?.tok else {
1153 unreachable!()
1154 };
1155 Expr::Str(s)
1156 }
1157 Token::LBrace => return self.table_constructor(),
1158 Token::Function => {
1159 let line = self.tok.line;
1160 self.advance()?;
1161 Expr::Function(self.func_body(line)?)
1162 }
1163 _ => return self.suffixed_expr(),
1164 };
1165 Ok(self.push_expr(e))
1166 }
1167
1168 fn primary_expr(&mut self) -> Result<ExprId, SyntaxError> {
1169 match &self.tok.tok {
1170 Token::Name(_) => {
1171 let name = self.expect_name()?;
1172 self.ident_lookup_51(&name.text)?;
1173 Ok(self.push_expr(Expr::Name(name)))
1174 }
1175 Token::LParen => {
1176 let line = self.tok.line;
1177 self.advance()?;
1178 let inner = self.expr()?;
1179 self.expect_match(Token::RParen, ")", "(", line)?;
1180 Ok(self.push_expr(Expr::Paren(inner)))
1181 }
1182 _ => Err(self.error("unexpected symbol")),
1183 }
1184 }
1185
1186 fn suffixed_expr(&mut self) -> Result<ExprId, SyntaxError> {
1187 let primary_line = self.tok.line;
1202 let mut e = self.primary_expr()?;
1203 loop {
1204 match &self.tok.tok {
1205 Token::Dot => {
1206 self.advance()?;
1207 let name = self.expect_name()?;
1208 let key = self.push_expr(Expr::Str(name.text.into_boxed_bytes().into_vec()));
1209 e = self.push_expr(Expr::Index { obj: e, key });
1210 }
1211 Token::LBracket => {
1212 self.advance()?;
1213 let key = self.expr()?;
1214 self.expect(Token::RBracket, "]")?;
1215 e = self.push_expr(Expr::Index { obj: e, key });
1216 }
1217 Token::Colon => {
1218 self.advance()?;
1219 let method = self.expect_name()?;
1220 let line = if self.version <= LuaVersion::Lua53 {
1221 primary_line
1222 } else {
1223 self.tok.line
1224 };
1225 let args = self.call_args()?;
1226 e = self.push_expr(Expr::MethodCall {
1227 obj: e,
1228 method,
1229 args,
1230 line,
1231 });
1232 }
1233 Token::LParen | Token::Str(_) | Token::LBrace => {
1234 let line = if self.version <= LuaVersion::Lua53 {
1235 primary_line
1236 } else {
1237 self.tok.line
1238 };
1239 let args = self.call_args()?;
1240 e = self.push_expr(Expr::Call {
1241 func: e,
1242 args,
1243 line,
1244 });
1245 }
1246 _ => break,
1247 }
1248 }
1249 Ok(e)
1250 }
1251
1252 fn call_args(&mut self) -> Result<Vec<ExprId>, SyntaxError> {
1253 match &self.tok.tok {
1254 Token::LParen => {
1255 if self.version == LuaVersion::Lua51 && self.tok.line != self.prev_line {
1257 return Err(self.error("ambiguous syntax (function call x new statement)"));
1258 }
1259 let line = self.tok.line;
1260 self.advance()?;
1261 let args = if self.tok.tok == Token::RParen {
1262 Vec::new()
1263 } else {
1264 self.exprlist()?
1265 };
1266 self.expect_match(Token::RParen, ")", "(", line)?;
1267 Ok(args)
1268 }
1269 Token::Str(_) => {
1270 let Token::Str(s) = self.advance()?.tok else {
1271 unreachable!()
1272 };
1273 Ok(vec![self.push_expr(Expr::Str(s))])
1274 }
1275 Token::LBrace => Ok(vec![self.table_constructor()?]),
1276 _ => Err(self.error("function arguments expected")),
1277 }
1278 }
1279
1280 fn table_constructor(&mut self) -> Result<ExprId, SyntaxError> {
1281 let line = self.tok.line;
1282 self.expect(Token::LBrace, "{")?;
1283 let mut fields = Vec::new();
1284 loop {
1285 if self.tok.tok == Token::RBrace {
1286 break;
1287 }
1288 if self.tok.tok == Token::LBracket {
1289 self.advance()?;
1290 let key = self.expr()?;
1291 self.expect(Token::RBracket, "]")?;
1292 self.expect(Token::Assign, "=")?;
1293 let value = self.expr()?;
1294 fields.push(TableField::Keyed(key, value));
1295 } else if matches!(self.tok.tok, Token::Name(_)) && *self.peek()? == Token::Assign {
1296 let name = self.expect_name()?;
1297 self.advance()?; let value = self.expr()?;
1299 fields.push(TableField::Named(name, value));
1300 } else {
1301 fields.push(TableField::Item(self.expr()?));
1302 }
1303 if !(self.accept(Token::Comma)? || self.accept(Token::Semi)?) {
1304 break;
1305 }
1306 }
1307 self.expect_match(Token::RBrace, "}", "{", line)?;
1308 Ok(self.push_expr(Expr::Table { fields, line }))
1309 }
1310
1311 fn func_body(&mut self, line: u32) -> Result<FuncBody, SyntaxError> {
1314 self.expect(Token::LParen, "(")?;
1315 self.func_local_count.push((0, line, 0));
1316 self.enter_fn_51(line);
1317 let mut params = Vec::new();
1318 let mut vararg = Vararg::None;
1319 if self.tok.tok != Token::RParen {
1320 loop {
1321 match &self.tok.tok {
1322 Token::Ellipsis => {
1323 self.advance()?;
1324 vararg = if self.version.has_named_vararg()
1325 && matches!(self.tok.tok, Token::Name(_))
1326 {
1327 Vararg::Named(self.expect_name()?)
1328 } else {
1329 Vararg::Anonymous
1330 };
1331 if let Vararg::Named(ref n) = vararg {
1332 self.new_local()?;
1333 self.add_local_51(&n.text);
1334 }
1335 break;
1336 }
1337 Token::Name(_) => {
1338 let p = self.expect_name()?;
1339 self.new_local()?;
1340 self.add_local_51(&p.text);
1341 params.push(p);
1342 }
1343 _ => return Err(self.error("<name> or '...' expected")),
1344 }
1345 if !self.accept(Token::Comma)? {
1346 break;
1347 }
1348 }
1349 }
1350 self.activate_locals()?;
1351 self.goto_step(|g| {
1352 g.enter_function();
1353 for p in ¶ms {
1354 g.declare(&p.text);
1355 }
1356 Ok(())
1357 })?;
1358 self.expect(Token::RParen, ")")?;
1359 self.funcs.push(FnFlow {
1360 vararg: !matches!(vararg, Vararg::None),
1361 loops: 0,
1362 });
1363 let block = self.block()?;
1364 let end_line = self.tok.line; self.expect_match(Token::End, "end", "function", line)?;
1366 self.close_function()?;
1367 self.func_local_count.pop();
1368 self.leave_fn_51();
1369 Ok(FuncBody {
1370 params,
1371 vararg,
1372 block,
1373 line,
1374 end_line,
1375 })
1376 }
1377
1378 fn track_uv_51(&self) -> bool {
1379 !self.upval_chain_51.is_empty()
1380 }
1381
1382 fn add_local_51(&mut self, name: &str) {
1383 if self.track_uv_51() {
1384 self.upval_chain_51
1385 .last_mut()
1386 .expect("fn ctx")
1387 .locals
1388 .push(name.into());
1389 }
1390 }
1391
1392 fn snap_locals_51(&self) -> usize {
1393 if self.track_uv_51() {
1394 self.upval_chain_51.last().expect("fn ctx").locals.len()
1395 } else {
1396 0
1397 }
1398 }
1399
1400 fn restore_locals_51(&mut self, snap: usize) {
1401 if self.track_uv_51() {
1402 self.upval_chain_51
1403 .last_mut()
1404 .expect("fn ctx")
1405 .locals
1406 .truncate(snap);
1407 }
1408 }
1409
1410 fn enter_fn_51(&mut self, line_defined: u32) {
1411 if self.track_uv_51() {
1412 self.upval_chain_51.push(FnUvSlot {
1413 line_defined,
1414 ..Default::default()
1415 });
1416 }
1417 }
1418
1419 fn leave_fn_51(&mut self) {
1420 if self.track_uv_51() {
1421 self.upval_chain_51.pop();
1422 }
1423 }
1424
1425 fn ident_lookup_51(&mut self, name: &str) -> Result<(), SyntaxError> {
1431 if !self.track_uv_51() {
1432 return Ok(());
1433 }
1434 const MAXUPVAL: usize = 60;
1435 let n = self.upval_chain_51.len();
1436 let mut owner: Option<usize> = None;
1437 for k in (0..n).rev() {
1438 if self.upval_chain_51[k]
1439 .locals
1440 .iter()
1441 .any(|s| s.as_ref() == name)
1442 {
1443 owner = Some(k);
1444 break;
1445 }
1446 }
1447 let Some(owner_idx) = owner else {
1448 return Ok(());
1449 };
1450 if owner_idx + 1 == n {
1451 return Ok(());
1452 }
1453 for k in (owner_idx + 1)..n {
1454 let inserted = self.upval_chain_51[k].upvalues.insert(name.into());
1455 if inserted && self.upval_chain_51[k].upvalues.len() > MAXUPVAL {
1456 let line_defined = self.upval_chain_51[k].line_defined;
1457 let where_ = if k == 0 {
1458 "main function".to_string()
1459 } else {
1460 format!("function at line {line_defined}")
1461 };
1462 return Err(SyntaxError {
1464 line: self.tok.line,
1465 msg: format!("{where_} has more than {MAXUPVAL} upvalues").into_bytes(),
1466 });
1467 }
1468 }
1469 Ok(())
1470 }
1471
1472 fn new_local(&mut self) -> Result<(), SyntaxError> {
1477 let &(active, line_defined, pending) = self.func_local_count.last().expect("func ctx");
1478 if self.version <= LuaVersion::Lua54 && active + pending + 1 > MAXVARS {
1479 return Err(if self.version <= LuaVersion::Lua51 {
1480 let what = if self.func_local_count.len() == 1 {
1481 "main function".to_string()
1482 } else {
1483 format!("function at line {line_defined}")
1484 };
1485 self.plain_error(format!("{what} has more than {MAXVARS} local variables"))
1486 } else {
1487 self.local_limit_error()
1488 });
1489 }
1490 self.func_local_count.last_mut().expect("func ctx").2 += 1;
1491 Ok(())
1492 }
1493
1494 fn activate_locals(&mut self) -> Result<(), SyntaxError> {
1497 let (active, _, pending) = *self.func_local_count.last().expect("func ctx");
1498 if self.version >= LuaVersion::Lua55 && active + pending > MAXVARS {
1499 return Err(self.local_limit_error());
1500 }
1501 let slot = self.func_local_count.last_mut().expect("func ctx");
1502 slot.0 += pending;
1503 slot.2 = 0;
1504 Ok(())
1505 }
1506
1507 fn local_limit_error(&self) -> SyntaxError {
1508 self.error(format!(
1509 "too many local variables (limit is {MAXVARS}) in {}",
1510 self.where_()
1511 ))
1512 }
1513}