diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8ebb199 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ldmc" +version = "0.1.0" +edition = "2024" + +[dependencies] +chumsky = "0.9.0" +ariadne = "0.2" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..5df47b9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,93 @@ +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() + }); + } + } +}