use crate::ast::{Exp, Parser};
use crate::error::{LuaError, Result};
use crate::lexer::{Pos, Spanned, Token};
pub struct Local {
pub vars: Vec<(String, Option<Attr>, Pos)>,
pub exps: Vec<Exp>,
}
#[derive(Clone, Copy)]
pub enum Attr {
Const,
Close,
}
impl<'a> Parser<'a> {
pub(super) fn parse_local(&mut self) -> Result<Local> {
let mut vars = vec![self.parse_name_attr()?];
loop {
match self.tok_peek_opt()?.map(Spanned::inner) {
Some(Token::Comma) => {
self.tok_next()?;
vars.push(self.parse_name_attr()?);
if vars.len() > 255 {
return err!(LuaError::SyntaxLimit("local variables", None));
}
}
Some(Token::Is) => {
self.tok_next()?;
break;
}
_ => {
return Ok(Local {
vars,
exps: Vec::new(),
})
}
}
}
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()?);
}
Ok(Local { vars, exps })
}
fn parse_name_attr(&mut self) -> Result<(String, Option<Attr>, Pos)> {
let (pos, name) = self.tok_ident()?;
let attr = match self.tok_peek_opt()?.map(Spanned::inner) {
Some(Token::Lt) => {
self.tok_next()?;
let attr = match self.tok_ident()?.1.as_str() {
"const" => Attr::Const,
"close" => Attr::Close,
attr => return err!(LuaError::UnknownAttribute(attr.to_string())),
};
tok_expect!(self, Token::Gt);
Some(attr)
}
_ => None,
};
Ok((name, attr, pos))
}
}