parser: small refactor around Invocations

TODO: merge Expression and Object, their distinction makes little sense
This commit is contained in:
Alain Zscheile 2023-05-22 00:58:10 +02:00
parent d17524a7d2
commit 599721de7c

View File

@ -36,8 +36,8 @@ pub struct Entry {
pub enum Object {
Code {
cfe: bool,
data: Box<[Statement]>,
ret: Option<Statement>,
data: Box<[Expression]>,
ret: Option<Box<Expression>>,
},
Module(Module),
Alias(FullIdentifier),
@ -58,22 +58,15 @@ pub struct Path {
}
#[derive(Clone, Debug)]
pub enum StmtArgs {
Single(Box<Object>),
Multi(BTreeMap<Box<[Atom]>, (Location, Object)>),
}
impl Default for StmtArgs {
#[inline]
fn default() -> Self {
StmtArgs::Multi(BTreeMap::new())
}
}
#[derive(Clone, Debug)]
pub struct Statement {
pub sel: FullIdentifier,
pub args: StmtArgs,
pub enum Expression {
InvocationSingle {
obj: Object,
arg: Object,
},
InvocationMulti {
obj: Object,
args: BTreeMap<Box<[Atom]>, (Location, Object)>,
},
}
pub struct Error {
@ -188,11 +181,11 @@ impl FullIdentifier {
}
}
impl Statement {
impl Expression {
fn parse_high(ctx: &mut ParserContext<'_>) -> Result<Self, Error> {
let sel = FullIdentifier::parse_high(ctx)?;
let obj = Object::parse_high(ctx)?;
let args = if let Some(&(_, Token::Comma)) = ctx.pklx.peek() {
Ok(if let Some(&(_, Token::Comma)) = ctx.pklx.peek() {
let mut args = BTreeMap::new();
while ctx.maybe_eat_token(Token::Comma).is_some() {
let Path { loc, idents } = Path::parse_high(ctx)?;
@ -205,16 +198,20 @@ impl Statement {
});
}
}
StmtArgs::Multi(args)
Expression::InvocationMulti { obj, args }
} else if matches!(ctx.pklx.peek(), Some(&(_, Token::SemiColon)) | None) {
// do nothing, there won't be an argument
// this escape hatch is a bit ugly, idk...
StmtArgs::default()
Expression::InvocationMulti {
obj,
args: BTreeMap::new(),
}
} else {
StmtArgs::Single(Box::new(Object::parse_high(ctx)?))
};
Ok(Statement { sel, args })
Expression::InvocationSingle {
obj,
arg: Object::parse_high(ctx)?,
}
})
}
}
@ -235,11 +232,11 @@ impl Object {
let mut codata = Vec::new();
let mut ret = None;
while ctx.maybe_eat_token(Token::CloseBrace).is_none() {
let stmt = Statement::parse_high(ctx)?;
let expr = Expression::parse_high(ctx)?;
if ctx.maybe_eat_token(Token::SemiColon).is_some() {
codata.push(stmt);
codata.push(expr);
} else {
ret = Some(stmt);
ret = Some(Box::new(expr));
// we don't go back to the loop header, so do it here.
ctx.expect_token(Token::CloseBrace, /* { */ "}")?;
break;