use crate::ast::{Exp, Parser, Stat};
use crate::error::{LuaError, Result};
use crate::lexer::{Pos, Spanned, Token};
use super::MAX_SCOPE;
pub struct Block {
pub stats: Vec<Stat>,
pub ret: Option<(Vec<Exp>, Pos)>,
}
impl<'a> Parser<'a> {
pub(super) fn parse_block(&mut self) -> Result<Block> {
let mut stats = Vec::new();
let mut ret = None;
self.scope_depth += 1;
if self.scope_depth > MAX_SCOPE {
return err!(LuaError::SyntaxLimit("nested scopes", None));
}
loop {
match self.tok_peek_opt()?.map(Into::into) {
None | Some((_, Token::Elseif | Token::Else | Token::Until | Token::End)) => break,
Some((pos, Token::Return)) => {
self.tok_next()?;
ret = Some((vec![], pos));
match self.tok_peek_opt()?.map(Spanned::inner) {
Some(Token::Elseif | Token::Else | Token::Until | Token::End) => break,
Some(Token::Semi) => {
self.tok_next()?;
break;
}
None => break, _ => {}
}
let mut exps = vec![self.parse_exp()?];
while let Some(Token::Comma) = self.tok_peek_opt()?.map(Spanned::inner) {
self.tok_next()?;
exps.push(self.parse_exp()?);
}
ret = Some((exps, pos));
if let Some(Token::Semi) = self.tok_peek_opt()?.map(Spanned::inner) {
self.tok_next()?;
}
break;
}
_ => stats.push(self.parse_stat()?),
}
}
self.scope_depth -= 1;
Ok(Block { stats, ret })
}
}