Skip to content

Commit

Permalink
🥢 Simplify parser
Browse files Browse the repository at this point in the history
Co-authored-by: lmittmann <[email protected]>
Co-authored-by: Philippe Dumonet <[email protected]>
  • Loading branch information
3 people authored Oct 18, 2024
1 parent d184772 commit f2455ee
Showing 1 changed file with 47 additions and 54 deletions.
101 changes: 47 additions & 54 deletions crates/ast/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ fn root<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Root<'src>>
}

fn root_section<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::RootSection<'src>> {
let definition = definition().map(ast::RootSection::Definition);
let include = just(Keyword("include"))
.ignore_then(select! {String(s) => s}.map_with(|s, ex| (s, ex.span())))
.map(ast::RootSection::Include);

choice((definition().map(ast::RootSection::Definition), include))
choice((definition, include))
}

fn definition<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Definition<'src>> {
Expand All @@ -83,28 +84,25 @@ fn definition<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Defin
}

fn r#macro<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Definition<'src>> {
let macro_args = ident().separated_by(just(Punct(','))).collect::<Vec<_>>();
let macro_args = ident().separated_by(punct(',')).collect::<Vec<_>>();

just(Ident("macro"))
.ignore_then(ident())
.then_ignore(just(Punct('(')))
.then(macro_args)
.then_ignore(just(Punct(')')))
.then_ignore(just(Punct('=')))
.then(macro_args.delimited_by(punct('('), punct(')')))
.then_ignore(punct('='))
.then(
just(Ident("takes"))
.ignore_then(just(Punct('(')))
.ignore_then(dec())
.then_ignore(just(Punct(')')))
.ignore_then(dec().delimited_by(punct('('), punct(')')))
.then_ignore(just(Ident("returns")))
.then_ignore(just(Punct('(')))
.then(dec())
.then_ignore(just(Punct(')')))
.then(dec().delimited_by(punct('('), punct(')')))
.or_not(),
)
.then_ignore(just(Punct('{')))
.then(macro_statement().repeated().collect::<Vec<_>>())
.then_ignore(just(Punct('}')))
.then(
macro_statement()
.repeated()
.collect::<Vec<_>>()
.delimited_by(punct('{'), punct('}')),
)
.map(|(((name, args), takes_returns), body)| ast::Macro {
name,
args: args.into_boxed_slice(),
Expand All @@ -117,7 +115,7 @@ fn r#macro<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Definiti
fn macro_statement<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::MacroStatement<'src>>
{
let label = ident()
.then_ignore(just(Punct(':')))
.then_ignore(punct(':'))
.map(ast::MacroStatement::LabelDefinition);
let instruction = instruction().map(ast::MacroStatement::Instruction);
let invoke = invoke().map(ast::MacroStatement::Invoke);
Expand Down Expand Up @@ -212,26 +210,21 @@ fn instruction<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Inst
ast::Instruction::LabelReference((ident, span))
}
});
let macro_arg_ref = just(Punct('<'))
.ignore_then(ident())
.then_ignore(just(Punct('>')))
let macro_arg_ref = ident()
.delimited_by(punct('<'), punct('>'))
.map(ast::Instruction::MacroArgReference);
let constant_ref = just(Punct('['))
.ignore_then(ident())
.then_ignore(just(Punct(']')))
let constant_ref = ident()
.delimited_by(punct('['), punct(']'))
.map(ast::Instruction::ConstantReference);

choice((push_auto, push, op, macro_arg_ref, constant_ref))
}

fn invoke<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Invoke<'src>> {
let invoke_macro_args = just(Punct('('))
.ignore_then(
instruction()
.separated_by(just(Punct(',')))
.collect::<Vec<_>>(),
)
.then_ignore(just(Punct(')')))
let invoke_macro_args = instruction()
.separated_by(punct(','))
.collect::<Vec<_>>()
.delimited_by(punct('('), punct(')'))
.map(|args| args.into_boxed_slice());

let invoke_macro = ident()
Expand All @@ -240,9 +233,9 @@ fn invoke<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Invoke<'s

let invoke_builtin = |name, constructor: fn((_, Span)) -> ast::Invoke<'src>| {
just(Ident(name))
.ignore_then(just(Punct('(')))
.ignore_then(punct('('))
.ignore_then(ident())
.then_ignore(just(Punct(')')))
.then_ignore(punct(')'))
.map(constructor)
};

Expand All @@ -269,17 +262,20 @@ fn constant<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Definit

just(Ident("constant"))
.ignore_then(ident())
.then_ignore(just(Punct('=')))
.then_ignore(punct('='))
.then(const_expr)
.map(|(name, expr)| ast::Definition::Constant { name, expr })
}

fn table<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Definition<'src>> {
just(Ident("table"))
.ignore_then(ident())
.then_ignore(just(Punct('{')))
.then(code().repeated().collect::<Vec<_>>())
.then_ignore(just(Punct('}')))
.then(
code()
.repeated()
.collect::<Vec<_>>()
.delimited_by(punct('{'), punct('}')),
)
.map(|(name, code)| ast::Definition::Table {
name,
data: code
Expand Down Expand Up @@ -330,41 +326,34 @@ fn sol_error<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, ast::Defini

fn sol_type_list<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, Box<[Spanned<DynSolType>]>>
{
just(Punct('('))
.ignore_then(
sol_type()
.separated_by(just(Punct(',')))
.collect::<Vec<_>>(),
)
.then_ignore(just(Punct(')')))
sol_type()
.separated_by(punct(','))
.collect::<Vec<_>>()
.delimited_by(punct('('), punct(')'))
.map(|args| args.into_boxed_slice())
}

fn sol_type<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, Spanned<DynSolType>> {
recursive(|sol_raw_type| {
let sol_raw_primitive_type = ident().map(|(typ, _)| typ.to_string()).boxed();
let sol_raw_primitive_type = ident().map(|(typ, _)| typ.to_string());

let sol_raw_tuple_type = just(Punct('('))
.ignore_then(
sol_raw_type
.separated_by(just(Punct(',')))
.collect::<Vec<_>>(),
)
.then_ignore(just(Punct(')')))
let sol_raw_tuple_type = sol_raw_type
.separated_by(punct(','))
.collect::<Vec<_>>()
.delimited_by(punct('('), punct(')'))
.map(|types| {
let mut result = "(".to_string();
let types = types.into_iter().collect::<Vec<_>>().join(",");
result.push_str(&types);
result.push(')');
result
})
.boxed();
});

choice((sol_raw_primitive_type, sol_raw_tuple_type))
.then(
just(Punct('['))
punct('[')
.ignore_then(dec().or_not())
.then_ignore(just(Punct(']')))
.then_ignore(punct(']'))
.or_not(),
)
.then_ignore(ident().or_not())
Expand Down Expand Up @@ -414,6 +403,10 @@ fn code<'tokens, 'src: 'tokens>() -> impl Parser<'tokens, 'src, Vec<u8>> {
.map(|code| code.to_vec())
}

fn punct<'tokens, 'src: 'tokens>(c: char) -> impl Parser<'tokens, 'src, Token<'src>> {
just(Punct(c))
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit f2455ee

Please sign in to comment.