1use super::lexer::{Token, TokenWithSpan};
4use super::ast::*;
5use std::fmt;
6
7#[derive(Debug)]
8pub struct ParseError {
9 pub message: String,
10 pub line: u32,
11}
12
13impl fmt::Display for ParseError {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 write!(f, "Parse error at line {}: {}", self.line, self.message)
16 }
17}
18
19pub struct Parser {
20 tokens: Vec<TokenWithSpan>,
21 pos: usize,
22 in_match_head: bool,
23 in_ternary: bool,
24 in_match_arm: bool,
25}
26
27impl Parser {
28 pub fn new(tokens: Vec<TokenWithSpan>) -> Self {
29 Self { tokens, pos: 0, in_match_head: false, in_ternary: false, in_match_arm: false }
30 }
31
32 pub fn from_source(name: &str, source: &str) -> Result<Script, ParseError> {
34 let mut lexer = super::lexer::Lexer::new(source);
35 let tokens = lexer.tokenize();
36 let mut parser = Parser::new(tokens);
37 parser.parse_script(name)
38 }
39
40 fn peek(&self) -> &Token {
41 self.tokens.get(self.pos).map(|t| &t.token).unwrap_or(&Token::Eof)
42 }
43
44 fn peek_span_line(&self) -> u32 {
45 self.tokens.get(self.pos).map(|t| t.span.line).unwrap_or(0)
46 }
47
48 fn advance(&mut self) -> &Token {
49 let t = self.tokens.get(self.pos).map(|t| &t.token).unwrap_or(&Token::Eof);
50 if self.pos < self.tokens.len() { self.pos += 1; }
51 t
52 }
53
54 fn expect(&mut self, expected: &Token) -> Result<(), ParseError> {
55 if self.peek() == expected {
56 self.advance();
57 Ok(())
58 } else {
59 Err(ParseError {
60 message: format!("expected {:?}, got {:?}", expected, self.peek()),
61 line: self.peek_span_line(),
62 })
63 }
64 }
65
66 fn expect_ident(&mut self) -> Result<String, ParseError> {
67 match self.peek().clone() {
68 Token::Ident(s) => { self.advance(); Ok(s) }
69 t => Err(ParseError { message: format!("expected identifier, got {:?}", t), line: self.peek_span_line() })
70 }
71 }
72
73 fn check(&self, t: &Token) -> bool { self.peek() == t }
74
75 fn consume_if(&mut self, t: &Token) -> bool {
76 if self.peek() == t { self.advance(); true }
77 else { false }
78 }
79
80 pub fn parse_script(&mut self, name: &str) -> Result<Script, ParseError> {
83 let stmts = self.parse_block()?;
84 Ok(Script { name: name.to_string(), stmts })
85 }
86
87 fn parse_block(&mut self) -> Result<Vec<Stmt>, ParseError> {
88 let mut stmts = Vec::new();
89 loop {
90 self.consume_if(&Token::Semicolon);
91 match self.peek() {
92 Token::Eof | Token::End | Token::Else | Token::ElseIf | Token::Until => break,
93 _ => {}
94 }
95 stmts.push(self.parse_stmt()?);
96 }
97 Ok(stmts)
98 }
99
100 fn parse_stmt(&mut self) -> Result<Stmt, ParseError> {
101 match self.peek().clone() {
102 Token::Local => self.parse_local(),
103 Token::Function => self.parse_func_decl(),
104 Token::If => self.parse_if(),
105 Token::While => self.parse_while(),
106 Token::For => self.parse_for(),
107 Token::Repeat => self.parse_repeat_until(),
108 Token::Do => { self.advance(); let b = self.parse_block()?; self.expect(&Token::End)?; Ok(Stmt::Do(b)) }
109 Token::Return => self.parse_return(),
110 Token::Break => { self.advance(); Ok(Stmt::Break) }
111 Token::Continue => { self.advance(); Ok(Stmt::Continue) }
112 Token::Match => self.parse_match(),
113 Token::Import => self.parse_import(),
114 Token::Export => { self.advance(); let name = self.expect_ident()?; Ok(Stmt::Export(name)) }
115 _ => self.parse_expr_stmt(),
116 }
117 }
118
119 fn parse_local(&mut self) -> Result<Stmt, ParseError> {
120 self.advance(); if self.check(&Token::Function) {
122 self.advance();
123 let name = self.expect_ident()?;
124 let (params, vararg, body) = self.parse_func_body()?;
125 return Ok(Stmt::LocalFunc { name, params, vararg, body });
126 }
127 let mut names = vec![self.expect_ident()?];
128 while self.consume_if(&Token::Comma) {
129 names.push(self.expect_ident()?);
130 }
131 let inits = if self.consume_if(&Token::Eq) {
132 self.parse_expr_list()?
133 } else { Vec::new() };
134
135 if names.len() == 1 && inits.len() <= 1 {
136 Ok(Stmt::LocalDecl { name: names.remove(0), init: inits.into_iter().next() })
137 } else {
138 Ok(Stmt::LocalMulti { names, inits })
139 }
140 }
141
142 fn parse_func_decl(&mut self) -> Result<Stmt, ParseError> {
143 self.advance(); let mut name = vec![self.expect_ident()?];
145 while self.consume_if(&Token::Dot) {
146 name.push(self.expect_ident()?);
147 }
148 let (params, vararg, body) = self.parse_func_body()?;
149 Ok(Stmt::FuncDecl { name, params, vararg, body })
150 }
151
152 fn parse_func_body(&mut self) -> Result<(Vec<String>, bool, Vec<Stmt>), ParseError> {
153 self.expect(&Token::LParen)?;
154 let mut params = Vec::new();
155 let mut vararg = false;
156 if !self.check(&Token::RParen) {
157 loop {
158 if self.check(&Token::DotDotDot) {
159 self.advance();
160 vararg = true;
161 break;
162 }
163 params.push(self.expect_ident()?);
164 if !self.consume_if(&Token::Comma) { break; }
165 }
166 }
167 self.expect(&Token::RParen)?;
168 let body = self.parse_block()?;
169 self.expect(&Token::End)?;
170 Ok((params, vararg, body))
171 }
172
173 fn parse_if(&mut self) -> Result<Stmt, ParseError> {
174 self.advance(); let cond = self.parse_expr(0)?;
176 self.expect(&Token::Then)?;
177 let then_body = self.parse_block()?;
178 let mut elseif_branches = Vec::new();
179 let mut else_body = None;
180 loop {
181 if self.consume_if(&Token::ElseIf) {
182 let ec = self.parse_expr(0)?;
183 self.expect(&Token::Then)?;
184 let eb = self.parse_block()?;
185 elseif_branches.push((ec, eb));
186 } else if self.consume_if(&Token::Else) {
187 else_body = Some(self.parse_block()?);
188 break;
189 } else { break; }
190 }
191 self.expect(&Token::End)?;
192 Ok(Stmt::If { cond, then_body, elseif_branches, else_body })
193 }
194
195 fn parse_while(&mut self) -> Result<Stmt, ParseError> {
196 self.advance();
197 let cond = self.parse_expr(0)?;
198 self.expect(&Token::Do)?;
199 let body = self.parse_block()?;
200 self.expect(&Token::End)?;
201 Ok(Stmt::While { cond, body })
202 }
203
204 fn parse_for(&mut self) -> Result<Stmt, ParseError> {
205 self.advance();
206 let first = self.expect_ident()?;
207 if self.consume_if(&Token::Eq) {
208 let start = self.parse_expr(0)?;
210 self.expect(&Token::Comma)?;
211 let limit = self.parse_expr(0)?;
212 let step = if self.consume_if(&Token::Comma) { Some(self.parse_expr(0)?) } else { None };
213 self.expect(&Token::Do)?;
214 let body = self.parse_block()?;
215 self.expect(&Token::End)?;
216 Ok(Stmt::NumericFor { var: first, start, limit, step, body })
217 } else {
218 let mut vars = vec![first];
220 while self.consume_if(&Token::Comma) { vars.push(self.expect_ident()?); }
221 self.expect(&Token::In)?;
222 let iter = self.parse_expr_list()?;
223 self.expect(&Token::Do)?;
224 let body = self.parse_block()?;
225 self.expect(&Token::End)?;
226 Ok(Stmt::GenericFor { vars, iter, body })
227 }
228 }
229
230 fn parse_repeat_until(&mut self) -> Result<Stmt, ParseError> {
231 self.advance();
232 let body = self.parse_block()?;
233 self.expect(&Token::Until)?;
234 let cond = self.parse_expr(0)?;
235 Ok(Stmt::RepeatUntil { body, cond })
236 }
237
238 fn parse_return(&mut self) -> Result<Stmt, ParseError> {
239 self.advance();
240 let vals = match self.peek() {
241 Token::End | Token::Else | Token::ElseIf | Token::Until | Token::Eof | Token::Semicolon => Vec::new(),
242 _ => self.parse_expr_list()?,
243 };
244 self.consume_if(&Token::Semicolon);
245 Ok(Stmt::Return(vals))
246 }
247
248 fn parse_match(&mut self) -> Result<Stmt, ParseError> {
249 self.advance();
250 self.in_match_head = true;
251 let expr = self.parse_expr(0)?;
252 self.in_match_head = false;
253 self.expect(&Token::LBrace)?;
254 let mut arms = Vec::new();
255 while !self.check(&Token::RBrace) && !self.check(&Token::Eof) {
256 self.consume_if(&Token::Case);
257 let pattern = self.parse_match_pattern()?;
258 if !self.consume_if(&Token::FatArrow) { self.expect(&Token::Arrow)?; }
259 let body = if self.check(&Token::LBrace) {
260 self.advance();
261 let b = self.parse_block()?;
262 self.expect(&Token::RBrace)?;
263 b
264 } else {
265 let old = self.in_match_arm;
266 self.in_match_arm = true;
267 let s = vec![self.parse_stmt()?];
268 self.in_match_arm = old;
269 s
270 };
271 arms.push(MatchArm { pattern, body });
272 self.consume_if(&Token::Comma);
273 }
274 self.expect(&Token::RBrace)?;
275 Ok(Stmt::Match { expr, arms })
276 }
277
278 fn parse_match_pattern(&mut self) -> Result<MatchPattern, ParseError> {
279 match self.peek().clone() {
280 Token::Ident(s) if s == "_" => { self.advance(); Ok(MatchPattern::Wildcard) }
281 Token::Default => { self.advance(); Ok(MatchPattern::Wildcard) }
282 _ => Ok(MatchPattern::Literal(self.parse_expr(0)?)),
283 }
284 }
285
286 fn parse_import(&mut self) -> Result<Stmt, ParseError> {
287 self.advance();
288 let path = match self.advance().clone() {
289 Token::Str(s) => s,
290 Token::Ident(s) => s,
291 t => return Err(ParseError { message: format!("expected module path, got {:?}", t), line: self.peek_span_line() }),
292 };
293 let alias = if self.consume_if(&Token::Ident("as".to_string())) {
294 Some(self.expect_ident()?)
295 } else { None };
296 Ok(Stmt::Import { path, alias })
297 }
298
299 fn parse_expr_stmt(&mut self) -> Result<Stmt, ParseError> {
300 let expr = self.parse_expr(0)?;
301
302 if self.check(&Token::Eq) || self.check(&Token::Comma) {
304 let mut targets = vec![expr];
305 while self.consume_if(&Token::Comma) {
306 targets.push(self.parse_expr(0)?);
307 }
308 self.expect(&Token::Eq)?;
309 let values = self.parse_expr_list()?;
310 return Ok(Stmt::Assign { target: targets, value: values });
311 }
312
313 let op = match self.peek() {
315 Token::PlusEq => Some(BinOp::Add),
316 Token::MinusEq => Some(BinOp::Sub),
317 Token::StarEq => Some(BinOp::Mul),
318 Token::SlashEq => Some(BinOp::Div),
319 _ => None,
320 };
321 if let Some(op) = op {
322 self.advance();
323 let value = self.parse_expr(0)?;
324 return Ok(Stmt::CompoundAssign { target: expr, op, value });
325 }
326
327 Ok(Stmt::Call(expr))
328 }
329
330 fn parse_expr_list(&mut self) -> Result<Vec<Expr>, ParseError> {
331 let mut exprs = vec![self.parse_expr(0)?];
332 while !self.in_match_arm && self.consume_if(&Token::Comma) {
333 exprs.push(self.parse_expr(0)?);
334 }
335 Ok(exprs)
336 }
337
338 fn parse_expr(&mut self, min_prec: u8) -> Result<Expr, ParseError> {
341 let mut lhs = self.parse_unary()?;
342
343 loop {
344 let op = match self.peek() {
345 Token::Plus => Some(BinOp::Add),
346 Token::Minus => Some(BinOp::Sub),
347 Token::Star => Some(BinOp::Mul),
348 Token::Slash => Some(BinOp::Div),
349 Token::SlashSlash => Some(BinOp::IDiv),
350 Token::Percent => Some(BinOp::Mod),
351 Token::Caret => Some(BinOp::Pow),
352 Token::DotDot => Some(BinOp::Concat),
353 Token::EqEq => Some(BinOp::Eq),
354 Token::NotEq => Some(BinOp::NotEq),
355 Token::Lt => Some(BinOp::Lt),
356 Token::LtEq => Some(BinOp::LtEq),
357 Token::Gt => Some(BinOp::Gt),
358 Token::GtEq => Some(BinOp::GtEq),
359 Token::And => Some(BinOp::And),
360 Token::Or => Some(BinOp::Or),
361 Token::Amp => Some(BinOp::BitAnd),
362 Token::Pipe => Some(BinOp::BitOr),
363 Token::Tilde => Some(BinOp::BitXor),
364 Token::ShiftLeft => Some(BinOp::Shl),
365 Token::ShiftRight => Some(BinOp::Shr),
366 _ => None,
367 };
368 if let Some(op) = op {
369 let prec = op.precedence();
370 if prec <= min_prec { break; }
371 self.advance();
372 let next_min = if op.is_right_assoc() { prec - 1 } else { prec };
373 let rhs = self.parse_expr(next_min)?;
374 lhs = Expr::Binary { op, lhs: Box::new(lhs), rhs: Box::new(rhs) };
375 } else { break; }
376 }
377 if self.check(&Token::Question) {
379 self.advance();
380 let old = self.in_ternary;
381 self.in_ternary = true;
382 let then_val = self.parse_expr(0)?;
383 self.in_ternary = old;
384 self.expect(&Token::Colon)?;
385 let else_val = self.parse_expr(0)?;
386 lhs = Expr::Ternary {
387 cond: Box::new(lhs),
388 then_val: Box::new(then_val),
389 else_val: Box::new(else_val),
390 };
391 }
392 Ok(lhs)
393 }
394
395 fn parse_unary(&mut self) -> Result<Expr, ParseError> {
396 match self.peek().clone() {
397 Token::Minus => { self.advance(); let e = self.parse_unary()?; Ok(Expr::Unary { op: UnOp::Neg, expr: Box::new(e) }) }
398 Token::Not | Token::Bang => { self.advance(); let e = self.parse_unary()?; Ok(Expr::Unary { op: UnOp::Not, expr: Box::new(e) }) }
399 Token::Hash => { self.advance(); let e = self.parse_unary()?; Ok(Expr::Unary { op: UnOp::Len, expr: Box::new(e) }) }
400 Token::Tilde => { self.advance(); let e = self.parse_unary()?; Ok(Expr::Unary { op: UnOp::BitNot, expr: Box::new(e) }) }
401 _ => self.parse_postfix(),
402 }
403 }
404
405 fn parse_postfix(&mut self) -> Result<Expr, ParseError> {
406 let mut expr = self.parse_primary()?;
407 loop {
408 match self.peek().clone() {
409 Token::Dot => {
410 self.advance();
411 let name = self.expect_ident()?;
412 expr = Expr::Field { table: Box::new(expr), name };
413 if self.check(&Token::LParen) {
415 let args = self.parse_args()?;
416 expr = Expr::Call { callee: Box::new(expr), args };
417 }
418 }
419 Token::Colon if !self.in_ternary => {
420 self.advance();
421 let method = self.expect_ident()?;
422 let args = self.parse_args()?;
423 expr = Expr::MethodCall { obj: Box::new(expr), method, args };
424 }
425 Token::LBracket => {
426 self.advance();
427 let key = self.parse_expr(0)?;
428 self.expect(&Token::RBracket)?;
429 expr = Expr::Index { table: Box::new(expr), key: Box::new(key) };
430 }
431 Token::LParen | Token::Str(_) => {
432 let args = self.parse_args()?;
433 expr = Expr::Call { callee: Box::new(expr), args };
434 }
435 Token::LBrace if !self.in_match_head => {
436 let args = self.parse_args()?;
437 expr = Expr::Call { callee: Box::new(expr), args };
438 }
439 _ => break,
440 }
441 }
442 Ok(expr)
443 }
444
445 fn parse_args(&mut self) -> Result<Vec<Expr>, ParseError> {
446 match self.peek().clone() {
447 Token::LParen => {
448 self.advance();
449 if self.check(&Token::RParen) { self.advance(); return Ok(Vec::new()); }
450 let args = self.parse_expr_list()?;
451 self.expect(&Token::RParen)?;
452 Ok(args)
453 }
454 Token::LBrace => {
455 let t = self.parse_table_ctor()?;
456 Ok(vec![t])
457 }
458 Token::Str(s) => { self.advance(); Ok(vec![Expr::Str(s)]) }
459 t => Err(ParseError { message: format!("expected args, got {:?}", t), line: self.peek_span_line() })
460 }
461 }
462
463 fn parse_primary(&mut self) -> Result<Expr, ParseError> {
464 match self.peek().clone() {
465 Token::Nil => { self.advance(); Ok(Expr::Nil) }
466 Token::True => { self.advance(); Ok(Expr::Bool(true)) }
467 Token::False => { self.advance(); Ok(Expr::Bool(false)) }
468 Token::Int(v) => { self.advance(); Ok(Expr::Int(v)) }
469 Token::Float(v) => { self.advance(); Ok(Expr::Float(v)) }
470 Token::Str(s) => { self.advance(); Ok(Expr::Str(s)) }
471 Token::DotDotDot => { self.advance(); Ok(Expr::Vararg) }
472 Token::Ident(s) => { self.advance(); Ok(Expr::Ident(s)) }
473 Token::LParen => {
474 self.advance();
475 let e = self.parse_expr(0)?;
476 self.expect(&Token::RParen)?;
477 Ok(e)
478 }
479 Token::LBrace => self.parse_table_ctor(),
480 Token::Function => {
481 self.advance();
482 let (params, vararg, body) = self.parse_func_body()?;
483 Ok(Expr::FuncExpr { params, vararg, body })
484 }
485 t => Err(ParseError { message: format!("unexpected token: {:?}", t), line: self.peek_span_line() })
486 }
487 }
488
489 fn parse_table_ctor(&mut self) -> Result<Expr, ParseError> {
490 self.expect(&Token::LBrace)?;
491 let mut fields = Vec::new();
492 while !self.check(&Token::RBrace) && !self.check(&Token::Eof) {
493 let field = if self.check(&Token::LBracket) {
494 self.advance();
495 let key = self.parse_expr(0)?;
496 self.expect(&Token::RBracket)?;
497 self.expect(&Token::Eq)?;
498 let val = self.parse_expr(0)?;
499 TableField::ExprKey(key, val)
500 } else if let Token::Ident(name) = self.peek().clone() {
501 if self.tokens.get(self.pos + 1).map(|t| &t.token) == Some(&Token::Eq) {
502 self.advance(); self.advance();
503 let val = self.parse_expr(0)?;
504 TableField::NameKey(name, val)
505 } else {
506 TableField::Value(self.parse_expr(0)?)
507 }
508 } else {
509 TableField::Value(self.parse_expr(0)?)
510 };
511 fields.push(field);
512 if !self.consume_if(&Token::Comma) && !self.consume_if(&Token::Semicolon) { break; }
513 }
514 self.expect(&Token::RBrace)?;
515 Ok(Expr::TableCtor(fields))
516 }
517}
518
519pub fn parse_named(name: &str, source: &str) -> Result<Script, ParseError> {
521 parse(source, name)
522}
523
524pub fn parse(source: &str, name: &str) -> Result<Script, ParseError> {
526 let mut lexer = super::lexer::Lexer::new(source);
527 let tokens = lexer.tokenize();
528 let mut parser = Parser::new(tokens);
529 parser.parse_script(name)
530}
531
532#[cfg(test)]
533mod tests {
534 use super::*;
535
536 fn parse_ok(src: &str) -> Script {
537 parse(src, "test").unwrap_or_else(|e| panic!("Parse failed: {}", e))
538 }
539
540 #[test]
541 fn test_parse_local_assign() {
542 let s = parse_ok("local x = 42");
543 assert_eq!(s.stmts.len(), 1);
544 assert!(matches!(&s.stmts[0], Stmt::LocalDecl { name, init: Some(Expr::Int(42)) } if name == "x"));
545 }
546
547 #[test]
548 fn test_parse_function() {
549 let s = parse_ok("function greet(name) return name end");
550 assert!(matches!(&s.stmts[0], Stmt::FuncDecl { .. }));
551 }
552
553 #[test]
554 fn test_parse_if_else() {
555 let s = parse_ok("if x > 0 then return 1 else return -1 end");
556 assert!(matches!(&s.stmts[0], Stmt::If { .. }));
557 }
558
559 #[test]
560 fn test_parse_while() {
561 let s = parse_ok("while i < 10 do i = i + 1 end");
562 assert!(matches!(&s.stmts[0], Stmt::While { .. }));
563 }
564
565 #[test]
566 fn test_parse_table_ctor() {
567 let s = parse_ok("local t = {x = 1, y = 2, 3}");
568 assert!(matches!(&s.stmts[0], Stmt::LocalDecl { init: Some(Expr::TableCtor(_)), .. }));
569 }
570
571 #[test]
572 fn test_parse_binary_expr() {
573 let s = parse_ok("local z = a + b * c");
574 if let Stmt::LocalDecl { init: Some(expr), .. } = &s.stmts[0] {
575 assert!(matches!(expr, Expr::Binary { op: BinOp::Add, .. }));
576 }
577 }
578
579 #[test]
580 fn test_parse_for_numeric() {
581 let s = parse_ok("for i = 1, 10, 2 do end");
582 assert!(matches!(&s.stmts[0], Stmt::NumericFor { var, .. } if var == "i"));
583 }
584
585 #[test]
586 fn test_parse_error() {
587 let result = parse("local = 123", "test");
588 assert!(result.is_err());
589 }
590}