initial parser for morphism-base using chumsky

This commit is contained in:
Michael Sippel 2025-01-29 11:33:01 +01:00
parent f65dfee2b3
commit d66dc0e78b
Signed by: senvas
GPG key ID: F96CF119C34B64A6
2 changed files with 101 additions and 0 deletions

8
Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "ldmc"
version = "0.1.0"
edition = "2024"
[dependencies]
chumsky = "0.9.0"
ariadne = "0.2"

93
src/main.rs Normal file
View file

@ -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()
});
}
}
}