use std::borrow::Cow;
use std::fmt::{self, Display};
use std::iter::Iterator;
use std::iter::Peekable;
use crate::ast::*;
use crate::lexer::{Lexer, LexerError};
use crate::span::{HasSpan, Span};
use crate::symbol::Symbol;
use crate::token::{Token, TokenKind};
#[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ParseError<'a> {
LexerError(LexerError),
UnexpectedToken {
expected: Cow<'static, [TokenKind]>,
found: TokenReference<'a>,
},
VarExpected {
expr: PrefixExpr<'a>,
},
StatementExpected {
expr: ParenthesizedExpr<'a>,
},
BreakOutsideLoop {
stat: BreakStat<'a>,
},
}
fn format_expected_list(expected: &[TokenKind]) -> String {
match expected.len() {
0 => "nothing".to_owned(),
1 => expected[0].to_string(),
2 => format!("{} or {}", expected[0], expected[1]),
_ => {
let mut tokens = expected
.iter()
.map(|kind| kind.to_string())
.collect::<Vec<_>>();
tokens.sort_unstable();
format!(
"one of {}, or {}",
tokens[..(tokens.len() - 1)].join(", "),
tokens[tokens.len() - 1],
)
},
}
}
impl Display for ParseError<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::LexerError(e) => e.to_string(),
Self::UnexpectedToken { expected, found } => format!(
"expected {}, found {}",
format_expected_list(expected),
found.token.kind()
),
Self::VarExpected { expr } => format!(
"expected a variable, found {}",
match expr {
PrefixExpr::Parenthesized(_) => "a parenthesized expression",
PrefixExpr::Call(_) => "a function call",
_ => unreachable!(),
}
),
Self::StatementExpected { .. } => {
"expected a statement, found a parenthesized expression".to_owned()
}
Self::BreakOutsideLoop { .. } => {
"the break statement is not enclosed in any loop".to_owned()
}
};
write!(formatter, "{}", s)
}
}
impl std::error::Error for ParseError<'_> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::LexerError(ref e) => Some(e),
_ => None,
}
}
}
impl HasSpan for ParseError<'_> {
fn span(&self) -> Span {
match self {
Self::LexerError(e) => e.span(),
Self::UnexpectedToken { found, .. } => found.span(),
Self::VarExpected { expr } => expr.span(),
Self::StatementExpected { expr } => expr.span(),
Self::BreakOutsideLoop { stat } => stat.span(),
}
}
}
#[derive(Clone, Debug)]
struct RefLexer<'a> {
lexer: Peekable<Lexer<'a>>,
saved: Option<Token<'a>>, leading_trivia: Vec<Token<'a>>,
trailing_trivia: Vec<Token<'a>>,
}
impl<'a> RefLexer<'a> {
fn new(lexer: Lexer<'a>) -> RefLexer<'a> {
RefLexer {
lexer: lexer.peekable(),
saved: None,
leading_trivia: Vec::new(),
trailing_trivia: Vec::new(),
}
}
}
impl<'a> Iterator for RefLexer<'a> {
type Item = Result<TokenReference<'a>, LexerError>;
fn next(&mut self) -> Option<Self::Item> {
let token = loop {
let saved = self.saved.take().map(Ok).into_iter();
let next = saved.chain(&mut self.lexer).next()?;
match next {
Ok(t) if t.kind().is_trivia() => {
self.leading_trivia.push(t);
}
Ok(t) => break t,
Err(e) => return Some(Err(e)),
}
};
loop {
match self.lexer.peek() {
Some(Ok(t)) if t.kind().is_trivia() => self
.trailing_trivia
.push(self.lexer.next().unwrap().unwrap()),
Some(Ok(_)) => {
self.saved = Some(self.lexer.next().unwrap().unwrap());
break;
}
_ => break,
}
}
Some(Ok(TokenReference {
leading_trivia: self.leading_trivia.drain(..).collect(),
token,
trailing_trivia: self.trailing_trivia.drain(..).collect(),
}))
}
}
#[derive(Clone, Debug)]
pub struct Parser<'a> {
lexer: Peekable<RefLexer<'a>>,
is_inside_loop: bool,
}
trait Expect {
fn matches(&self, token: TokenKind) -> bool;
fn to_token_kinds(&self) -> Cow<'static, [TokenKind]>;
}
impl Expect for &'static [TokenKind] {
fn matches(&self, token: TokenKind) -> bool {
self.contains(&token)
}
fn to_token_kinds(&self) -> Cow<'static, [TokenKind]> {
(*self).into()
}
}
impl Expect for &'_ [Symbol] {
fn matches(&self, token: TokenKind) -> bool {
if let TokenKind::Symbol(symbol) = token {
self.contains(&symbol)
} else {
false
}
}
fn to_token_kinds(&self) -> Cow<'static, [TokenKind]> {
self.iter().copied().map(TokenKind::Symbol).collect()
}
}
impl<T: Clone + Into<TokenKind>> Expect for T {
fn matches(&self, token: TokenKind) -> bool {
self.clone().into() == token
}
fn to_token_kinds(&self) -> Cow<'static, [TokenKind]> {
vec![self.clone().into()].into()
}
}
macro_rules! lookahead {
($s:ident { $($expect:expr => $expr:expr,)+ _ => $catch:expr, }) => ({
match $s.lexer.peek() {
$(Some(Ok(t)) if $expect.matches(t.token.kind()) => $expr,)+
_ => $catch,
}
});
($s:ident { $($expect:expr => $expr:expr,)+ }) => ({
let expected = || {
vec![$($expect.to_token_kinds().into_owned(), )+].into_iter().flatten().collect()
};
match $s.lexer.peek() {
$(Some(Ok(t)) if $expect.matches(t.token.kind()) => $expr,)+
Some(Ok(t)) => return Err(ParseError::UnexpectedToken {
expected: expected(),
found: t.clone(),
}),
Some(Err(e)) => return Err(ParseError::LexerError(e.clone())),
None => panic!("lookahead called after reaching end of file"),
}
})
}
impl<'a> Parser<'a> {
pub fn new(lexer: Lexer<'a>) -> Parser<'a> {
Parser {
lexer: RefLexer::new(lexer).peekable(),
is_inside_loop: false,
}
}
pub fn chunk(&mut self) -> Result<Block<'a>, ParseError<'a>> {
let block = self.block()?;
self.expect(TokenKind::Eof)?;
Ok(block)
}
fn expect(&mut self, variants: impl Expect) -> Result<TokenReference<'a>, ParseError<'a>> {
match self.lexer.next() {
Some(Ok(t)) if variants.matches(t.token.kind()) => Ok(t),
Some(Ok(t)) => Err(ParseError::UnexpectedToken {
expected: variants.to_token_kinds(),
found: t,
}),
Some(Err(e)) => Err(ParseError::LexerError(e)),
None => panic!("expect called after reaching eof of file"),
}
}
fn number(&mut self) -> Result<NumberLit<'a>, ParseError<'a>> {
self.expect(TokenKind::Number).map(NumberLit)
}
fn nil(&mut self) -> Result<NilLit<'a>, ParseError<'a>> {
self.expect(Symbol::Nil).map(NilLit)
}
fn boolean(&mut self) -> Result<BooleanLit<'a>, ParseError<'a>> {
self.expect(BooleanLit::TOKEN_KINDS).map(BooleanLit)
}
fn string(&mut self) -> Result<StringLit<'a>, ParseError<'a>> {
self.expect(TokenKind::String).map(StringLit)
}
fn name(&mut self) -> Result<Name<'a>, ParseError<'a>> {
self.expect(TokenKind::Ident).map(Name)
}
fn table_constructor(&mut self) -> Result<TableConstructor<'a>, ParseError<'a>> {
let opening = self.expect(Symbol::CurlyBracketLeft)?;
let mut fields = Vec::<TableField<'a>>::new();
let closing = loop {
if let Some(last) = fields.last_mut() {
if last.separator.is_none() {
let t = self.expect(
&[Symbol::Comma, Symbol::Semicolon, Symbol::CurlyBracketRight][..],
)?;
if t.token.kind() == TokenKind::Symbol(Symbol::CurlyBracketRight) {
break t;
} else {
last.separator = Some(t);
}
}
}
let (key, value) = lookahead!(self {
Symbol::CurlyBracketRight => {
break self.expect(Symbol::CurlyBracketRight)?
},
TokenKind::Ident => {
let key = self.name()?;
lookahead!(self {
Symbol::Assign => {
let eq = self.expect(Symbol::Assign)?;
let value = self.expr()?;
(Some((TableKey::Name { key }, eq)), value)
},
_ => {
let prefix = self.prefix_expr_right(PrefixExpr::Var(Var::Name(key)))?;
let expr = self.expr_rec_right(Expr::Prefix(prefix), 0)?;
(None, expr)
},
})
},
Symbol::SquareBracketLeft => {
let opening = self.expect(Symbol::SquareBracketLeft)?;
let key = Box::new(self.expr()?);
let closing = self.expect(Symbol::SquareBracketRight)?;
let eq = self.expect(Symbol::Assign)?;
let value = self.expr()?;
let key = TableKey::Expr {
brackets: Brackets(opening, closing), key,
};
(Some((key, eq)), value)
},
_ => (None, self.expr()?),
});
fields.push(TableField {
key,
value: Box::new(value),
separator: None,
});
};
Ok(TableConstructor {
brackets: Brackets(opening, closing),
fields,
})
}
fn unop(&mut self) -> Result<UnOp<'a>, ParseError<'a>> {
self.expect(UnOp::TOKEN_KINDS).map(UnOp)
}
fn binop(&mut self) -> Result<BinOp<'a>, ParseError<'a>> {
self.expect(BinOp::TOKEN_KINDS).map(BinOp)
}
fn peek_binop(&mut self) -> Option<BinOpKind> {
let t = self.lexer.peek()?.as_ref().ok()?;
match t.token.kind() {
TokenKind::Symbol(s) => BinOpKind::from_symbol(s),
_ => None,
}
}
fn var_field(&mut self) -> Result<VarField<'a>, ParseError<'a>> {
lookahead!(self {
Symbol::Period => {
let period = self.expect(Symbol::Period)?;
let key = self.name()?;
Ok(VarField::Name { period, key })
},
Symbol::SquareBracketLeft => {
let opening = self.expect(Symbol::SquareBracketLeft)?;
let key = Box::new(self.expr()?);
let closing = self.expect(Symbol::SquareBracketRight)?;
Ok(VarField::Expr { brackets: Brackets(opening, closing), key })
},
})
}
fn punctuated<T, P>(
&mut self,
sep: impl Expect + Clone,
mut f: P,
) -> Result<Punctuated<'a, T>, ParseError<'a>>
where
P: FnMut(&mut Self) -> Result<T, ParseError<'a>>,
{
let mut pairs = Vec::new();
let first = f(self)?;
pairs.push((first, None));
loop {
lookahead!(self {
&sep => {
let separator = self.expect(sep.clone())?;
pairs.last_mut().unwrap().1.replace(separator);
pairs.push((f(self)?, None));
},
_ => break,
});
}
Ok(Punctuated { pairs })
}
fn parenthesized_list<T, F>(&mut self, f: F) -> Result<ParenthesizedList<'a, T>, ParseError<'a>>
where
F: FnMut(&mut Self) -> Result<T, ParseError<'a>>,
{
let opening = self.expect(Symbol::RoundBracketLeft)?;
let list = lookahead!(self {
Symbol::RoundBracketRight => {
Punctuated { pairs: Vec::new() }
},
_ => self.punctuated(Symbol::Comma, f)?,
});
let closing = self.expect(Symbol::RoundBracketRight)?;
let brackets = Brackets(opening, closing);
Ok(ParenthesizedList { brackets, list })
}
fn function_call(
&mut self,
prefix_expr: PrefixExpr<'a>,
) -> Result<FunctionCall<'a>, ParseError<'a>> {
let callee = lookahead!(self {
Symbol::Colon => {
let colon = self.expect(Symbol::Colon)?;
let name = self.name()?;
FunctionCallee::Method {
object: Box::new(prefix_expr),
colon,
name,
}
},
_ => FunctionCallee::Expr(Box::new(prefix_expr)),
});
let args = lookahead!(self {
Symbol::CurlyBracketLeft => {
FunctionArgs::TableConstructor(self.table_constructor()?)
},
TokenKind::String => {
FunctionArgs::StringLit(self.string()?)
},
Symbol::RoundBracketLeft => {
FunctionArgs::ParenthesizedList(
self.parenthesized_list(|s| s.expr().map(Box::new))?
)
},
});
Ok(FunctionCall { callee, args })
}
fn prefix_expr_right(
&mut self,
mut left: PrefixExpr<'a>,
) -> Result<PrefixExpr<'a>, ParseError<'a>> {
const CALL_TOKENS: &[TokenKind] = &[
TokenKind::Symbol(Symbol::CurlyBracketLeft),
TokenKind::String,
TokenKind::Symbol(Symbol::RoundBracketLeft),
TokenKind::Symbol(Symbol::Colon),
];
loop {
lookahead!(self {
&[Symbol::SquareBracketLeft, Symbol::Period][..] => {
let field = self.var_field()?;
left = PrefixExpr::Var(Var::Field(Box::new(left), field));
},
CALL_TOKENS => {
left = PrefixExpr::Call(self.function_call(left)?);
},
_ => break,
});
}
Ok(left)
}
fn prefix_expr(&mut self) -> Result<PrefixExpr<'a>, ParseError<'a>> {
let left = lookahead!(self {
Symbol::RoundBracketLeft => {
PrefixExpr::Parenthesized(self.parenthesized_expr()?)
},
TokenKind::Ident => {
PrefixExpr::Var(Var::Name(self.name()?))
},
});
self.prefix_expr_right(left)
}
fn parenthesized_expr(&mut self) -> Result<ParenthesizedExpr<'a>, ParseError<'a>> {
let opening = self.expect(Symbol::RoundBracketLeft)?;
let expr = self.expr()?;
let closing = self.expect(Symbol::RoundBracketRight)?;
Ok(ParenthesizedExpr {
brackets: Brackets(opening, closing),
expr: Box::new(expr),
})
}
pub fn expr(&mut self) -> Result<Expr<'a>, ParseError<'a>> {
self.expr_rec(0)
}
fn expr_rec(&mut self, min_bp: u8) -> Result<Expr<'a>, ParseError<'a>> {
let left = lookahead!(self {
Symbol::Nil => {
Expr::Nil(self.nil()?)
},
BooleanLit::TOKEN_KINDS => {
Expr::Boolean(self.boolean()?)
},
TokenKind::Number => {
Expr::Number(self.number()?)
},
TokenKind::String => {
Expr::String(self.string()?)
},
Symbol::TriplePeriod => {
Expr::Vararg(self.vararg()?)
},
Symbol::CurlyBracketLeft => {
Expr::TableConstructor(self.table_constructor()?)
},
&[TokenKind::Ident, TokenKind::Symbol(Symbol::RoundBracketLeft)][..] => {
Expr::Prefix(self.prefix_expr()?)
},
Symbol::Function => Expr::Function(self.function_expr()?),
UnOp::TOKEN_KINDS => {
let op = self.unop()?;
let ((), r_bp) = op.kind().binding_power();
let right = self.expr_rec(r_bp)?;
Expr::UnOp(UnOpExpr {
op, right: Box::new(right)
})
},
});
self.expr_rec_right(left, min_bp)
}
fn expr_rec_right(
&mut self,
mut left: Expr<'a>,
min_bp: u8,
) -> Result<Expr<'a>, ParseError<'a>> {
while let Some(op_kind) = self.peek_binop() {
let (l_bp, r_bp) = op_kind.binding_power();
if l_bp < min_bp {
break;
}
let op = self.binop()?;
let right = self.expr_rec(r_bp)?;
left = Expr::BinOp(BinOpExpr {
left: Box::new(left),
op,
right: Box::new(right),
});
}
Ok(left)
}
const TERMINATORS: &'static [TokenKind] = &[
TokenKind::Symbol(Symbol::End),
TokenKind::Symbol(Symbol::Until),
TokenKind::Symbol(Symbol::Else),
TokenKind::Symbol(Symbol::ElseIf),
TokenKind::Eof,
];
pub fn block(&mut self) -> Result<Block<'a>, ParseError<'a>> {
let mut statements = Vec::new();
while let Some(t) = self.lexer.peek().and_then(|v| v.as_ref().ok()) {
if t.token.kind() == TokenKind::Symbol(Symbol::Return) {
statements.push(Statement::Return(self.return_stat()?));
break;
}
if Self::TERMINATORS.contains(&t.token.kind()) {
break;
}
statements.push(self.statement()?);
}
Ok(Block { statements })
}
fn empty_stat(&mut self) -> Result<EmptyStat<'a>, ParseError<'a>> {
let semi = self.expect(Symbol::Semicolon)?;
Ok(EmptyStat(semi))
}
fn block_stat(&mut self) -> Result<BlockStat<'a>, ParseError<'a>> {
let do_ = self.expect(Symbol::Do)?;
let block = Box::new(self.block()?);
let end = self.expect(Symbol::End)?;
Ok(BlockStat { do_, block, end })
}
fn while_stat(&mut self) -> Result<WhileStat<'a>, ParseError<'a>> {
let was_inside_loop = self.is_inside_loop;
self.is_inside_loop = true;
let stat = WhileStat {
while_: self.expect(Symbol::While)?,
condition: Box::new(self.expr()?),
do_: self.expect(Symbol::Do)?,
block: Box::new(self.block()?),
end: self.expect(Symbol::End)?,
};
self.is_inside_loop = was_inside_loop;
Ok(stat)
}
fn generic_for(
&mut self,
for_: TokenReference<'a>,
names: Punctuated<'a, Name<'a>>,
) -> Result<GenericFor<'a>, ParseError<'a>> {
Ok(GenericFor {
for_,
names,
in_: self.expect(Symbol::In)?,
exprs: self.punctuated(Symbol::Comma, |s| s.expr().map(Box::new))?,
do_: self.expect(Symbol::Do)?,
block: Box::new(self.block()?),
end: self.expect(Symbol::End)?,
})
}
fn numerical_for(
&mut self,
for_: TokenReference<'a>,
mut names: Punctuated<'a, Name<'a>>,
) -> Result<NumericalFor<'a>, ParseError<'a>> {
Ok(NumericalFor {
for_,
name: names.pairs.remove(0).0,
assign: self.expect(Symbol::Assign)?,
from: Box::new(self.expr()?),
comma: self.expect(Symbol::Comma)?,
to: Box::new(self.expr()?),
step: lookahead!(self {
Symbol::Comma => {
let comma = self.expect(Symbol::Comma)?;
let expr = Box::new(self.expr()?);
Some((comma, expr))
},
_ => None,
}),
do_: self.expect(Symbol::Do)?,
block: Box::new(self.block()?),
end: self.expect(Symbol::End)?,
})
}
fn for_stat(&mut self) -> Result<ForStat<'a>, ParseError<'a>> {
let was_inside_loop = self.is_inside_loop;
self.is_inside_loop = true;
let for_ = self.expect(Symbol::For)?;
let names = self.punctuated(Symbol::Comma, Self::name)?;
let stat = if names.pairs.len() > 1 {
self.generic_for(for_, names).map(ForStat::Generic)?
} else {
lookahead!(self {
Symbol::In => {
self.generic_for(for_, names).map(ForStat::Generic)?
},
Symbol::Assign => {
self.numerical_for(for_, names).map(ForStat::Numerical)?
},
})
};
self.is_inside_loop = was_inside_loop;
Ok(stat)
}
fn return_stat(&mut self) -> Result<ReturnStat<'a>, ParseError<'a>> {
let return_ = self.expect(Symbol::Return)?;
let next = self.lexer.peek().and_then(|v| v.as_ref().ok());
let has_expr = next
.filter(|t| !Self::TERMINATORS.contains(&t.token.kind()))
.is_some();
let exprs = if has_expr {
self.punctuated(Symbol::Comma, |s| s.expr().map(Box::new))?
} else {
Punctuated { pairs: Vec::new() }
};
let semi = lookahead!(self {
Symbol::Semicolon => {
self.expect(Symbol::Semicolon).map(Some)?
},
_ => None,
});
Ok(ReturnStat {
return_,
exprs,
semi,
})
}
fn break_stat(&mut self) -> Result<BreakStat<'a>, ParseError<'a>> {
let stat = self.expect(Symbol::Break).map(BreakStat)?;
if self.is_inside_loop {
Ok(stat)
} else {
Err(ParseError::BreakOutsideLoop { stat })
}
}
pub fn statement(&mut self) -> Result<Statement<'a>, ParseError<'a>> {
lookahead!(self {
Symbol::Semicolon => self.empty_stat().map(Statement::Empty),
Symbol::Do => self.block_stat().map(Statement::Block),
Symbol::While => self.while_stat().map(Statement::While),
Symbol::For => self.for_stat().map(Statement::For),
Symbol::Repeat => self.repeat_stat().map(Statement::Repeat),
Symbol::Return => self.return_stat().map(Statement::Return),
Symbol::Break => self.break_stat().map(Statement::Break),
Symbol::Function => self.function_declaration(None).map(Statement::FunctionDeclaration),
Symbol::DoubleColon => self.label_stat().map(Statement::Label),
Symbol::Goto => self.goto_stat().map(Statement::Goto),
Symbol::If => self.if_stat().map(Statement::If),
&[TokenKind::Symbol(Symbol::RoundBracketLeft), TokenKind::Ident][..] => {
let expr = self.prefix_expr()?;
match expr {
PrefixExpr::Var(var) => self.assignment(var).map(Statement::Assignment),
PrefixExpr::Call(call) => Ok(Statement::FunctionCall(call)),
PrefixExpr::Parenthesized(expr) => Err(ParseError::StatementExpected { expr })
}
},
Symbol::Local => self.local(),
})
}
fn var(&mut self) -> Result<Var<'a>, ParseError<'a>> {
match self.prefix_expr()? {
PrefixExpr::Var(v) => Ok(v),
expr => Err(ParseError::VarExpected { expr }),
}
}
fn varlist(&mut self, first: Var<'a>) -> Result<Punctuated<'a, Var<'a>>, ParseError<'a>> {
let mut first = (first, None);
let list = lookahead!(self {
Symbol::Comma => {
first.1 = self.expect(Symbol::Comma).map(Some)?;
let mut rest = self.punctuated(Symbol::Comma, |s| s.var())?;
rest.pairs.insert(0, first);
rest
},
_ => Punctuated { pairs: vec![first] },
});
Ok(list)
}
fn assignment(&mut self, first: Var<'a>) -> Result<AssignmentStat<'a>, ParseError<'a>> {
let vars = self.varlist(first)?;
let assign = self.expect(Symbol::Assign)?;
let exprs = self.punctuated(Symbol::Comma, |s| s.expr().map(Box::new))?;
Ok(AssignmentStat {
vars,
assign,
exprs,
})
}
fn local(&mut self) -> Result<Statement<'a>, ParseError<'a>> {
let local = self.expect(Symbol::Local)?;
lookahead!(self {
Symbol::Function => {
self.function_declaration(Some(local)).map(Statement::FunctionDeclaration)
},
_ => self.local_declaration(local).map(Statement::LocalDeclaration),
})
}
fn local_declaration(
&mut self,
local: TokenReference<'a>,
) -> Result<LocalDeclarationStat<'a>, ParseError<'a>> {
let names = self.punctuated(Symbol::Comma, |s| s.name())?;
let definition = lookahead!(self {
Symbol::Assign => {
let assign = self.expect(Symbol::Assign)?;
let exprs = self.punctuated(
Symbol::Comma,
|s| s.expr().map(Box::new)
)?;
Some(LocalDefinition { assign, exprs })
},
_ => None,
});
Ok(LocalDeclarationStat {
local,
names,
definition,
})
}
fn function_declaration(
&mut self,
local: Option<TokenReference<'a>>,
) -> Result<FunctionDeclarationStat<'a>, ParseError<'a>> {
let function = self.expect(Symbol::Function)?;
Ok(match local {
Some(local) => {
let name = self.name()?;
let body = self.function_body()?;
FunctionDeclarationStat::Local {
local,
function,
name,
body,
}
}
None => {
let name = self.function_name()?;
let body = self.function_body()?;
FunctionDeclarationStat::Nonlocal {
function,
name,
body,
}
}
})
}
fn function_name(&mut self) -> Result<FunctionName<'a>, ParseError<'a>> {
let mut name = self.punctuated(Symbol::Period, |s| s.name())?;
Ok(lookahead!(self {
Symbol::Colon => {
let colon = self.expect(Symbol::Colon)?;
let method = self.name()?;
FunctionName::Method {
receiver: name,
colon,
method
}
},
_ => if name.pairs.len() == 1 {
FunctionName::PlainName(name.pairs.remove(0).0)
} else {
FunctionName::Indexed(name)
},
}))
}
fn function_body(&mut self) -> Result<FunctionBody<'a>, ParseError<'a>> {
let was_inside_loop = self.is_inside_loop;
self.is_inside_loop = false;
let mut params = Vec::new();
let opening = self.expect(Symbol::RoundBracketLeft)?;
let mut vararg = None;
let closing = lookahead!(self {
Symbol::RoundBracketRight => self.expect(Symbol::RoundBracketRight)?,
Symbol::TriplePeriod => {
vararg.replace(self.vararg()?);
self.expect(Symbol::RoundBracketRight)?
},
_ => {
params.push((self.name()?, None));
loop {
lookahead!(self {
Symbol::Comma => {
params.last_mut().unwrap().1.replace(self.expect(Symbol::Comma)?);
lookahead!(self {
Symbol::TriplePeriod => {
vararg.replace(self.vararg()?);
break self.expect(Symbol::RoundBracketRight)?;
},
_ => params.push((self.name()?, None)),
});
},
Symbol::RoundBracketRight => break self.expect(Symbol::RoundBracketRight)?,
});
}
},
});
let block = Box::new(self.block()?);
let end = self.expect(Symbol::End)?;
let params = ParenthesizedList {
brackets: Brackets(opening, closing),
list: Punctuated { pairs: params },
};
self.is_inside_loop = was_inside_loop;
Ok(FunctionBody {
params,
vararg,
block,
end,
})
}
fn vararg(&mut self) -> Result<Vararg<'a>, ParseError<'a>> {
self.expect(Symbol::TriplePeriod).map(Vararg)
}
fn function_expr(&mut self) -> Result<FunctionExpr<'a>, ParseError<'a>> {
let function = self.expect(Symbol::Function)?;
let body = self.function_body()?;
Ok(FunctionExpr { function, body })
}
fn repeat_stat(&mut self) -> Result<RepeatStat<'a>, ParseError<'a>> {
let was_inside_loop = self.is_inside_loop;
self.is_inside_loop = true;
let repeat = self.expect(Symbol::Repeat)?;
let block = Box::new(self.block()?);
let until = self.expect(Symbol::Until)?;
let condition = self.expr()?;
self.is_inside_loop = was_inside_loop;
Ok(RepeatStat {
repeat,
block,
until,
condition,
})
}
fn label_stat(&mut self) -> Result<LabelStat<'a>, ParseError<'a>> {
let preceding = self.expect(Symbol::DoubleColon)?;
let name = self.name()?;
let following = self.expect(Symbol::DoubleColon)?;
Ok(LabelStat {
preceding,
name,
following,
})
}
fn goto_stat(&mut self) -> Result<GotoStat<'a>, ParseError<'a>> {
let goto = self.expect(Symbol::Goto)?;
let label = self.name()?;
Ok(GotoStat { goto, label })
}
fn if_stat(&mut self) -> Result<IfStat<'a>, ParseError<'a>> {
let if_ = self.expect(Symbol::If)?;
let condition = self.expr()?;
let then = self.expect(Symbol::Then)?;
let block = Box::new(self.block()?);
let mut elseifs = Vec::new();
loop {
lookahead!(self {
Symbol::ElseIf => {
elseifs.push(self.else_if()?);
},
_ => break,
})
}
let else_ = lookahead!(self {
Symbol::Else => Some(self.else_()?),
_ => None,
});
let end = self.expect(Symbol::End)?;
Ok(IfStat {
if_,
condition,
then,
block,
elseifs,
else_,
end,
})
}
fn else_if(&mut self) -> Result<ElseIf<'a>, ParseError<'a>> {
let elseif = self.expect(Symbol::ElseIf)?;
let condition = self.expr()?;
let then = self.expect(Symbol::Then)?;
let block = self.block()?;
Ok(ElseIf {
elseif,
condition,
then,
block,
})
}
fn else_(&mut self) -> Result<Else<'a>, ParseError<'a>> {
let else_ = self.expect(Symbol::Else)?;
let block = self.block()?;
Ok(Else { else_, block })
}
}