diff --git a/crates/wafl-parser/src/parser.rs b/crates/wafl-parser/src/parser.rs index 495eecf..7d00a5c 100644 --- a/crates/wafl-parser/src/parser.rs +++ b/crates/wafl-parser/src/parser.rs @@ -27,13 +27,13 @@ pub struct Entry { // technically this is a set, but that would just waste space here... pub args: Box<[Atom]>, // might be a dummy - pub obj: Option, + pub obj: Option, // we use a bitflag here to conserve memory pub flags: EntryFlags, } #[derive(Clone, Debug)] -pub enum Object { +pub enum Expression { Code { cfe: bool, data: Box<[Expression]>, @@ -42,6 +42,11 @@ pub enum Object { Module(Module), Alias(FullIdentifier), Integer(i64), + InvocationSingle(Box<(Expression, Expression)>), + InvocationMulti { + obj: Box, + args: BTreeMap, (Location, Expression)>, + }, } #[derive(Clone, Debug)] @@ -57,18 +62,6 @@ pub struct Path { pub idents: Box<[Atom]>, } -#[derive(Clone, Debug)] -pub enum Expression { - InvocationSingle { - obj: Object, - arg: Object, - }, - InvocationMulti { - obj: Object, - args: BTreeMap, (Location, Object)>, - }, -} - pub struct Error { pub loc: Location, pub kind: ErrorKind, @@ -182,40 +175,6 @@ impl FullIdentifier { } impl Expression { - fn parse_high(ctx: &mut ParserContext<'_>) -> Result { - let obj = Object::parse_high(ctx)?; - - 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)?; - ctx.expect_token(Token::Assign, "=")?; - let obj = Object::parse_high(ctx)?; - if args.insert(idents, (loc, obj)).is_some() { - return Err(Error { - loc, - kind: ErrorKind::DuplicateIdentifier, - }); - } - } - 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... - Expression::InvocationMulti { - obj, - args: BTreeMap::new(), - } - } else { - Expression::InvocationSingle { - obj, - arg: Object::parse_high(ctx)?, - } - }) - } -} - -impl Object { fn parse_high(ctx: &mut ParserContext<'_>) -> Result { let mut cfe = false; for (_, i) in ctx.pklx.peeking_take_while(|(_, t)| t.is_cobj_attr()) { @@ -225,7 +184,7 @@ impl Object { } } - match ctx.pklx.peek() { + let obj = match ctx.pklx.peek() { None => Err(ctx.make_eof()), Some((_, Token::OpenBrace)) => { ctx.pklx.next(); @@ -242,7 +201,7 @@ impl Object { break; } } - Ok(Object::Code { + Ok(Expression::Code { cfe, data: codata.into_boxed_slice(), ret, @@ -257,17 +216,40 @@ impl Object { // expect a single code object descriptor => alias, or number. Some(&(_, Token::Integer(i))) => { ctx.pklx.next(); - Ok(Object::Integer(i)) + Ok(Expression::Integer(i)) } Some((_, Token::Module)) => { ctx.pklx.next(); ctx.expect_token(Token::OpenBrace, "{")?; let m = Module::parse_high(ctx)?; ctx.expect_token(Token::CloseBrace, "}")?; - Ok(Object::Module(m)) + Ok(Expression::Module(m)) } - _ => FullIdentifier::parse_high(ctx).map(Object::Alias), - } + _ => FullIdentifier::parse_high(ctx).map(Expression::Alias), + }?; + + 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)?; + ctx.expect_token(Token::Assign, "=")?; + let obj = Expression::parse_high(ctx)?; + if args.insert(idents, (loc, obj)).is_some() { + return Err(Error { + loc, + kind: ErrorKind::DuplicateIdentifier, + }); + } + } + Expression::InvocationMulti { + obj: Box::new(obj), + args, + } + } else if matches!(ctx.pklx.peek(), Some(&(_, Token::SemiColon)) | None) { + obj + } else { + Expression::InvocationSingle(Box::new((obj, Expression::parse_high(ctx)?))) + }) } } @@ -346,8 +328,8 @@ impl Module { } let obj = if ctx.maybe_eat_token(Token::Assign).is_some() { - let obj = Object::parse_high(ctx)?; - if let Object::Code { cfe: true, .. } = obj { + let obj = Expression::parse_high(ctx)?; + if let Expression::Code { cfe: true, .. } = obj { flags |= EntryFlags::CTRLFE; } Some(obj) @@ -355,7 +337,6 @@ impl Module { None }; - // code object ret.entries.insert( name, Entry {