use crate::ast::{Block, Parser};
use crate::error::{LuaError, Result};
use crate::lexer::{Pos, Spanned, Token};
pub struct Func {
pub params: Vec<String>,
pub varargs: bool,
pub block: Box<Block>,
pub pos_start: Pos,
pub pos_end: Pos,
}
impl<'a> Parser<'a> {
pub(super) fn parse_func(&mut self) -> Result<Func> {
let (params, varargs, pos_start) = self.parse_params()?;
let block = self.parse_block().map_err(|e| {
e.map_lua_error(|l| match l {
LuaError::SyntaxLimit(what, None) => {
LuaError::SyntaxLimit(what, Some(pos_start.line()))
}
l => l,
})
})?;
let pos_end = tok_expect!(self, Token::End);
Ok(Func {
params,
varargs,
block: Box::new(block),
pos_start,
pos_end,
})
}
fn parse_params(&mut self) -> Result<(Vec<String>, bool, Pos)> {
let pos_start = tok_expect!(self, Token::ParO);
let mut params = Vec::new();
let mut varargs = false;
if let Some(Token::ParC) = self.tok_peek_opt()?.map(Spanned::inner) {
self.tok_next()?;
return Ok((params, varargs, pos_start));
}
loop {
match self.tok_next()?.into() {
(_, Token::Ident(name)) => {
params.push(name.to_string());
match self.tok_next()?.into() {
(_, Token::Comma) => {}
(_, Token::ParC) => break,
(pos, tok) => {
return err!(&*self.source, pos, LuaError::UnexpectedToken(tok))
}
}
}
(_, Token::Dots) => {
varargs = true;
tok_expect!(self, Token::ParC);
break;
}
(_, Token::ParC) => break,
(pos, tok) => return err!(&*self.source, pos, LuaError::UnexpectedToken(tok)),
}
}
Ok((params, varargs, pos_start))
}
}