use crate::T;
use crate::ast::Expression;
use crate::ast::FunctionPartialApplication;
use crate::ast::Identifier;
use crate::ast::LocalIdentifier;
use crate::ast::PartialApplication;
use crate::ast::ast::Construct;
use crate::ast::ast::DieConstruct;
use crate::ast::ast::EmptyConstruct;
use crate::ast::ast::EvalConstruct;
use crate::ast::ast::ExitConstruct;
use crate::ast::ast::IncludeConstruct;
use crate::ast::ast::IncludeOnceConstruct;
use crate::ast::ast::IssetConstruct;
use crate::ast::ast::PrintConstruct;
use crate::ast::ast::RequireConstruct;
use crate::ast::ast::RequireOnceConstruct;
use crate::error::ParseError;
use crate::parser::Parser;
use crate::token::Precedence;
impl<'input, 'arena> Parser<'input, 'arena> {
pub(crate) fn parse_construct(&mut self) -> Result<Expression<'arena>, ParseError> {
let token = self.stream.lookahead(0)?.ok_or_else(|| self.stream.unexpected(None, &[]))?;
Ok(Expression::Construct(match token.kind {
T!["isset"] => {
let isset = self.expect_keyword(T!["isset"])?;
let result = self.parse_comma_separated_sequence(T!["("], T![")"], |p| p.parse_expression())?;
Construct::Isset(IssetConstruct {
isset,
left_parenthesis: result.open,
values: result.sequence,
right_parenthesis: result.close,
})
}
T!["empty"] => Construct::Empty(EmptyConstruct {
empty: self.expect_keyword(T!["empty"])?,
left_parenthesis: self.stream.eat_span(T!["("])?,
value: self.arena.alloc(self.parse_expression()?),
right_parenthesis: self.stream.eat_span(T![")"])?,
}),
T!["eval"] => Construct::Eval(EvalConstruct {
eval: self.expect_keyword(T!["eval"])?,
left_parenthesis: self.stream.eat_span(T!["("])?,
value: self.arena.alloc(self.parse_expression()?),
right_parenthesis: self.stream.eat_span(T![")"])?,
}),
T!["print"] => Construct::Print(PrintConstruct {
print: self.expect_keyword(T!["print"])?,
value: self.arena.alloc(self.parse_expression_with_precedence(Precedence::Print)?),
}),
T!["require"] => Construct::Require(RequireConstruct {
require: self.expect_any_keyword()?,
value: self.arena.alloc(self.parse_expression()?),
}),
T!["require_once"] => Construct::RequireOnce(RequireOnceConstruct {
require_once: self.expect_any_keyword()?,
value: self.arena.alloc(self.parse_expression()?),
}),
T!["include"] => Construct::Include(IncludeConstruct {
include: self.expect_any_keyword()?,
value: self.arena.alloc(self.parse_expression()?),
}),
T!["include_once"] => Construct::IncludeOnce(IncludeOnceConstruct {
include_once: self.expect_any_keyword()?,
value: self.arena.alloc(self.parse_expression()?),
}),
T!["exit"] => {
let exit = self.expect_any_keyword()?;
if let Some(next) = self.stream.lookahead(0)?
&& matches!(next.kind, T!["("])
{
let partial_args = self.parse_partial_argument_list()?;
if partial_args.has_placeholders() {
return Ok(Expression::PartialApplication(PartialApplication::Function(
FunctionPartialApplication {
function: self.arena.alloc(Expression::Identifier(Identifier::Local(
LocalIdentifier { span: exit.span, value: exit.value },
))),
argument_list: partial_args,
},
)));
} else {
Construct::Exit(ExitConstruct {
exit,
arguments: Some(partial_args.into_argument_list(self.arena)),
})
}
} else {
Construct::Exit(ExitConstruct { exit, arguments: None })
}
}
T!["die"] => {
let die = self.expect_any_keyword()?;
if let Some(next) = self.stream.lookahead(0)?
&& matches!(next.kind, T!["("])
{
let partial_args = self.parse_partial_argument_list()?;
if partial_args.has_placeholders() {
return Ok(Expression::PartialApplication(PartialApplication::Function(
FunctionPartialApplication {
function: self.arena.alloc(Expression::Identifier(Identifier::Local(
LocalIdentifier { span: die.span, value: die.value },
))),
argument_list: partial_args,
},
)));
} else {
Construct::Die(DieConstruct {
die,
arguments: Some(partial_args.into_argument_list(self.arena)),
})
}
} else {
Construct::Die(DieConstruct { die, arguments: None })
}
}
_ => {
return Err(self.stream.unexpected(
Some(token),
T![
"isset",
"empty",
"eval",
"include",
"include_once",
"require",
"require_once",
"print",
"exit",
"die"
],
));
}
}))
}
}