use { ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::{ prelude::*, text::* } }; #[derive(Debug)] struct Morphism { symbol: String, src_type: String, dst_type: String, type_args: Vec<(String, String)>, locations: Vec<String> } /* morphism-base text format: * NAME '(' [TYPE-ARG-NAME ':' KIND] ')' * SRC-TYPE * '-->' DST-TYPE * '@' [ LOCATION ':' ] */ fn parser() -> impl Parser<char, Vec<Morphism>, Error = Simple<char>> { ident().padded() .then( ident().padded() .then_ignore(just(':').padded()) .then(none_of(",)").repeated().padded()) .separated_by(just(',').padded()) .delimited_by(just('('), just(')')) ) .then_ignore(just('\n')) .then( take_until(just("-->").ignored()) .then(take_until(just('@').ignored())) ) .then( none_of(":\n").repeated().separated_by(just(':')) ) .map(|(((symbol, type_args), ((src_type, _), (dst_type, _))), locations)| { Morphism { symbol, src_type: src_type.iter().collect(), dst_type: dst_type.iter().collect(), type_args: type_args.into_iter().map(|(v,k)| (v,k.into_iter().collect())).collect(), locations: locations.into_iter().map(|l| l.into_iter().collect()).collect() } }) .separated_by(text::newline()) } fn main() { println!("Hello, world!"); let src = " morph_digit_as_char_to_uint8 (Radix:ℤ_16) <Digit Radix> ~ Char ~ Ascii ~ Byte --> <Digit Radix> ~ x86.UInt8 ~ Byte @lib/libmorph_posint.so:src/posint.c morph_string_as_nullterm_to_length_prefix () [~<ValueDelim '\0'> Char ~ Ascii] --> [~<LengthPrefix x86.UInt64> Char ~ Ascii] @lib/libmorph_length-prefix.so:src/length_prefix.c morph_string_as_length_prefix_to_nullterm () [~<LengthPrefix x86.UInt64> Char ~ Ascii] --> [~<ValueDelim '\0'> Char ~ Ascii] @lib/libmorph_length-prefix.so:src/length_prefix.c "; let result = parser().parse(src); match result { Ok(morphisms) => { println!("parse ok.\n{:?}", morphisms); } Err(errs) => { errs.into_iter().for_each(|e| { Report::build(ReportKind::Error, (), e.span().start) .with_message(e.to_string()) .with_label( Label::new(e.span()) .with_message(e) .with_color(Color::Red), ) .finish() .print(Source::from(&src)) .unwrap() }); } } }