From 7aa98bdd04f48e34469f25a2586b5cbfbaed4019 Mon Sep 17 00:00:00 2001 From: Jolimaitre Matthieu Date: Wed, 25 May 2022 20:09:59 +0300 Subject: [PATCH] started grammar parsing --- Cargo.lock | 99 ++++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 7 +- src/syntax_tree.rs | 72 +++++++++++++++++++ src/syntax_tree/parser.rs | 144 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 src/syntax_tree/parser.rs diff --git a/Cargo.lock b/Cargo.lock index 1018079..9dce2db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,105 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ahash" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" +dependencies = [ + "const-random", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chumsky" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4" +dependencies = [ + "ahash", +] + +[[package]] +name = "const-random" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40" +dependencies = [ + "getrandom", + "lazy_static", + "proc-macro-hack", + "tiny-keccak", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "prout" version = "0.1.0" +dependencies = [ + "chumsky", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/Cargo.toml b/Cargo.toml index b345a3d..6b24bee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chumsky = "0.8.0" diff --git a/src/main.rs b/src/main.rs index 38b3733..9879362 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,12 @@ pub mod syntax_tree; pub mod value; fn main() { - println!("Hello, world!"); + use prelude::std_prelude; + let input = todo!(); + // let parsed = syntax_tree::parser::Parser::parse(input); + // let executable = execution_tree::parser::Parser::parse(parsed, |b| std_prelude(b)); + // let runtime = runtime::Runtime::new(); + // runtime.execute(&executable); } #[test] diff --git a/src/syntax_tree.rs b/src/syntax_tree.rs index d81bbb5..18f24af 100644 --- a/src/syntax_tree.rs +++ b/src/syntax_tree.rs @@ -9,6 +9,10 @@ pub struct Program { pub struct Expr(pub Box); impl Expr { + pub fn new(inner: ExprInner) -> Self { + Self(Box::new(inner)) + } + pub fn inner(&self) -> &ExprInner { let Self(inner) = self; inner @@ -76,6 +80,72 @@ impl Expr { } } +impl From for Expr { + fn from(input: Scope) -> Self { + Self::new(ExprInner::Scope(input)) + } +} + +impl From for Expr { + fn from(input: Literal) -> Self { + Self::new(ExprInner::Literal(input)) + } +} + +impl From for Expr { + fn from(input: VarDef) -> Self { + Self::new(ExprInner::VarDef(input)) + } +} + +impl From for Expr { + fn from(input: VarAssign) -> Self { + Self::new(ExprInner::VarAssign(input)) + } +} + +impl From for Expr { + fn from(input: VarCall) -> Self { + Self::new(ExprInner::VarCall(input)) + } +} + +impl From for Expr { + fn from(input: FnDef) -> Self { + Self::new(ExprInner::FnDef(input)) + } +} + +impl From for Expr { + fn from(input: FnCall) -> Self { + Self::new(ExprInner::FnCall(input)) + } +} + +impl From for Expr { + fn from(input: FnRet) -> Self { + Self::new(ExprInner::FnRet(input)) + } +} + +impl From for Expr { + fn from(input: Loop) -> Self { + Self::new(ExprInner::Loop(input)) + } +} + +impl From for Expr { + fn from(input: LoopBr) -> Self { + Self::new(ExprInner::LoopBr(input)) + } +} + +impl From for Expr { + fn from(input: Cond) -> Self { + Self::new(ExprInner::Cond(input)) + } +} + impl From for Expr where T: Into, @@ -164,3 +234,5 @@ pub struct Cond { pub arm_true: Expr, pub arm_false: Option, } + +pub mod parser; diff --git a/src/syntax_tree/parser.rs b/src/syntax_tree/parser.rs new file mode 100644 index 0000000..5fed656 --- /dev/null +++ b/src/syntax_tree/parser.rs @@ -0,0 +1,144 @@ +use chumsky::prelude::*; + +use super::*; + +pub fn scope_parser() -> impl Parser> { + expression_parser() + .chain( + just(';') + .padded() + .ignore_then(expression_parser()) + .repeated(), + ) + .delimited_by(just('{'), just('}')) + .map(|instructions| Scope { instructions }) +} + +pub fn literal_value() -> impl Parser> { + let frac = just('.').chain(text::digits(10)); + let number = just('-') + .or_not() + .chain(text::int(10)) + .chain::(frac.or_not().flatten()) + .collect::() + .from_str() + .unwrapped(); + let literal = number.clone().map(|n| Value::Number(n)); // TODO: add other types + literal +} + +pub fn name() -> impl Parser> { + let name = just('a') + .or(just('b')) + .or(just('c')) + .or(just('d')) + .or(just('e')) + .or(just('f')) + .or(just('g')) + .or(just('h')) + .or(just('i')) + .or(just('j')) + .or(just('k')) + .or(just('l')) + .or(just('m')) + .or(just('n')) + .or(just('o')) + .or(just('p')) + .or(just('q')) + .or(just('r')) + .or(just('s')) + .or(just('t')) + .or(just('u')) + .or(just('v')) + .or(just('w')) + .or(just('x')) + .or(just('y')) + .or(just('z')) + .or(just('-')) + .or(just('_')) + .repeated() + .map(|v| String::from_iter(&v)); + name +} + +pub fn variable_definition_parser() -> impl Parser> { + name() + .padded() + .then_ignore(just(":")) + .padded() + .then(expression_parser()) + .map(|(name, value)| VarDef { name, value }) +} + +pub fn variable_assignement_parser() -> impl Parser> { + expression_parser().then() name() +} + +pub fn expression_parser() -> impl Parser> { + let scope = scope_parser().map(|s| s.into()); + let litteral = literal_value().map(|v| Expr::new_literal(v)); + let variable_definition = variable_definition_parser().map(|s| s.into()); + let variable_assignment; + let variable_call; + let function_definition; + let function_call; + let function_return; + let loop_; + let loop_break; + let condition; + scope + .or(litteral) + .or(variable_definition) + .or(variable_assignment) + .or(variable_call) + .or(function_definition) + .or(function_call) + .or(function_return) + .or(loop_) + .or(loop_break) + .or(condition) +} + +pub fn parser() -> impl Parser> { + let scope = expression_parser().chain( + just(';') + .padded() + .ignore_then(expression_parser()) + .repeated(), + ); + + let program = scope + .map(|instructions| { + let body = Scope { instructions }; + Program { body } + }) + .then_ignore(end().recover_with(skip_then_retry_until([]))); + program +} + +// impl Parser { +// pub fn parse(input: &str) -> Program { +// todo!() +// } +// } + +/* +// example + +my-print: (input) => { + concatenated: { + "now I would like to interject for a moment" + input + }; + print(input); +} + +a: 5.2; +loop { + if a <= 0 { + break true + } else { + a - 1 -> a + } +} + +*/