use crate::ast::{Exp, Parser, PrefixExp};
use crate::error::{LuaError, Result};
use crate::lexer::{Pos, Spanned, Token};
use super::MAX_ASSIGN;
pub struct Ass {
pub vars: Vec<(Var, Pos)>,
pub exps: Vec<Exp>,
}
pub enum Var {
Name(String),
Index(PrefixExp, Exp),
}
impl<'a> Parser<'a> {
pub(super) fn parse_ass(&mut self, first: PrefixExp) -> Result<Ass> {
let mut vars = vec![self.parse_var(Some(first))?];
loop {
match self.tok_next()?.into() {
(pos, Token::Comma) => {
if vars.len() > MAX_ASSIGN {
return err!(self.source, pos, LuaError::SyntaxLimit("assignments", None));
}
vars.push(self.parse_var(None)?)
}
(_, Token::Is) => break,
(pos, tok) => return err!(&*self.source, pos, LuaError::UnexpectedToken(tok)),
}
}
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(Ass { vars, exps })
}
fn parse_var(&mut self, parsed: Option<PrefixExp>) -> Result<(Var, Pos)> {
let prefix_exp = match parsed {
Some(exp) => exp,
None => self.parse_prefix_exp()?,
};
Ok(match prefix_exp {
PrefixExp::Var(name, pos) => (Var::Name(name), pos),
PrefixExp::Index(sub, exp, pos) => (Var::Index(*sub, *exp), pos),
_ => panic!(),
})
}
}