diff --git a/rust/Cargo.lock b/rust/Cargo.lock deleted file mode 100644 index dff9ea4..0000000 --- a/rust/Cargo.lock +++ /dev/null @@ -1,212 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "libc" -version = "0.2.167" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" - -[[package]] -name = "lino" -version = "0.0.1" -dependencies = [ - "pest", - "pest_derive", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "pest" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - -[[package]] -name = "proc-macro2" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "syn" -version = "2.0.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 458e0fc..9d7614c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lino" version = "0.0.1" -edition = "2021" +edition = "2024" [dependencies] pest = "2.1.3" diff --git a/rust/src/Test.pest b/rust/src/Test.pest deleted file mode 100644 index 5f07c79..0000000 --- a/rust/src/Test.pest +++ /dev/null @@ -1,24 +0,0 @@ -whitespace = _{ ("\n" | " ")+ } -ref_commons = _{ "(" | ":" | ")" } - -reference = @{ ( !ref_commons ~ !whitespace ~ ANY)+ } -point = _{ "(" ~ whitespace? ~ reference ~ whitespace? ~ ")" } - -values = _{ (link ~ whitespace?)* } -value = _{ "(" ~ whitespace? ~ values ~ whitespace? ~ ")"} - -link = { point | value | real_link | reference } -real_link = _{ "(" ~ whitespace? ~ (id ~ whitespace? ~ ":")? ~ whitespace? ~ values ~ whitespace? ~ ")" } -id = @{ reference } - -//element = _{ link ~ whitespace? ~ lines? } -element = _{ link } -lines = _{ top_first ~ ("\n" ~ top_continue)* } -top_first = _{ element ~ ("\n" ~ children)? } -top_continue = _{ PEEK_ALL ~ element ~ ("\n" ~ children)? } - -indentation = _{ (" ")+ } -children = { PEEK_ALL ~ PUSH(indentation) ~ lines ~ DROP } - -/// ORANGE -document = { whitespace? ~ lines ~ whitespace? } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index b770590..0afcf39 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,252 +1,122 @@ -pub mod lino { - - use pest::error::Error; - use pest::iterators::{Pair, Pairs}; - use pest::Parser; - use std::fmt; - // use std::mem; - - #[derive(Debug, Clone)] - pub enum LiNo { - Link { id: Option, values: Vec }, - Ref(T), - } - - impl LiNo { - pub fn is_ref(&self) -> bool { - matches!(self, LiNo::Ref(_)) - } - - pub fn is_link(&self) -> bool { - matches!(self, LiNo::Link { .. }) - } - } - - impl fmt::Display for LiNo { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - LiNo::Ref(value) => write!(f, "{}", value.to_string()), - LiNo::Link { id, values } => { - let id_str = id - .as_ref() - .map(|id| format!("{}: ", id.to_string())) - .unwrap_or_default(); - - if f.alternate() { - // Format top-level as lines - let lines = values - .iter() - .map(|value| format!("{}{}", id_str, value)) - .collect::>() - .join("\n"); - write!(f, "{}", lines) - } else { - let values_str = values - .iter() - .map(|value| value.to_string()) - .collect::>() - .join(" "); - write!(f, "({}{})", id_str, values_str) - } - } - } - } - } - - #[derive(pest_derive::Parser)] - #[grammar = "Test.pest"] - struct LiNoParser; - - fn parse_link_or_ref(pair: Pair) -> LiNo { - match pair.as_rule() { - Rule::link => { - let mut id = None; - let mut values = Vec::new(); - - let mut pairs = pair.into_inner(); - let first = pairs.next().unwrap(); - - if first.as_rule() == Rule::id { - id = Some(first.as_str().to_string()); - } else { - values.push(parse_link_or_ref(first)); - } - - for value in pairs { - values.push(parse_link_or_ref(value)); - } - if values.len() == 1 { - if let LiNo::Ref(val) = values.pop().unwrap() { - LiNo::Ref(val) - } else { - LiNo::Link { id, values } - } - } else { - LiNo::Link { id, values } - } - } - Rule::reference => LiNo::Ref(pair.as_str().to_string()), - _ => unreachable!(), - } - } - - fn parse_lino_values(pairs: Pairs) -> Result>, Error> { - let mut result = Vec::new(); - let pairs: Vec<_> = pairs.collect(); - for i in 0..pairs.len() { - let pair = pairs[i].clone(); - if pair.as_rule() == Rule::children { - continue; - } - let value = parse_link_or_ref(pair); - if let Some(children) = pairs.get(i + 1) { - if children.as_rule() == Rule::children { - for child in children.clone().into_inner() { - let child = parse_link_or_ref(child); - match child { - LiNo::Link { id, values } => { - result.push(LiNo::Link { - id, - values: [vec![value.clone()], values].concat(), - }); - } - LiNo::Ref(id) => { - result.push(LiNo::Link { - id: None, - values: vec![value.clone(), LiNo::Ref(id)], - }); - } - } - } - } - } - result.push(value); - } - Ok(result) - } - - pub fn parse_lino(document: &str) -> Result, Error> { - let document = LiNoParser::parse(Rule::document, document)?.next().unwrap(); - - let root = LiNo::Link { - id: None, - values: parse_lino_values(document.into_inner())?, - }; - - Ok(root) - } +#![feature(iter_intersperse)] + +mod lino; + +pub use lino::LiNo; + +pub fn parse_str(str: &str) -> Result, ()> { + Ok(LiNo::Ref(String::new())) } #[cfg(test)] mod tests { - use super::lino::*; - - #[test] - fn test_simple_link() { - let input = "(1: 1 1)"; - let parsed = parse_lino(input).expect("Failed to parse input"); - - // Validate regular formatting - let output = parsed.to_string(); - let expected = "((1: 1 1))"; // Expected regular output - assert_eq!(expected, output); - - // Validate alternate formatting - let output_alternate = format!("{:#}", parsed); - assert_eq!(input, output_alternate); - } - - #[test] - fn test_multiline_simple_links() { - let input = "(1: 1 1)\n(2: 2 2)"; - let parsed = parse_lino(input).expect("Failed to parse input"); - - // Validate regular formatting - let output = parsed.to_string(); - let expected = "((1: 1 1) (2: 2 2))"; // Expected regular output - assert_eq!(expected, output); - - // Validate alternate formatting - let output_alternate = format!("{:#}", parsed); - assert_eq!(input, output_alternate); - } - - #[test] - fn test_link_with_source_target() { - let input = "(index: source target)"; - let parsed = parse_lino(input).expect("Failed to parse input"); - - // Validate regular formatting - let output = parsed.to_string(); - let expected = "((index: source target))"; // Expected regular output - assert_eq!(expected, output); - - // Validate alternate formatting - let output_alternate = format!("{:#}", parsed); - assert_eq!(input, output_alternate); - } - - #[test] - fn test_link_with_source_type_target() { - let input = "(index: source type target)"; - let parsed = parse_lino(input).expect("Failed to parse input"); - - // Validate regular formatting - let output = parsed.to_string(); - let expected = "((index: source type target))"; // Expected regular output - assert_eq!(expected, output); - - // Validate alternate formatting - let output_alternate = format!("{:#}", parsed); - assert_eq!(input, output_alternate); - } - - #[test] - fn test_is_ref() { - let reference = LiNo::Ref("some_value".to_string()); - assert!(reference.is_ref()); - assert!(!reference.is_link()); - } - - #[test] - fn test_is_link() { - let link = LiNo::Link { - id: Some("id".to_string()), - values: vec![LiNo::Ref("child".to_string())], - }; - assert!(link.is_link()); - assert!(!link.is_ref()); - } - - #[test] - fn test_empty_link() { - let link = LiNo::Link:: { - id: None, - values: vec![], - }; - let output = link.to_string(); - assert_eq!(output, "()"); - } - - #[test] - fn test_nested_links() { - let input = "(1: (2: (3: 3)))"; - let parsed = parse_lino(input).expect("Failed to parse input"); - - // Validate regular formatting - let output = parsed.to_string(); - let expected = "((1: (2: (3: 3))))"; - assert_eq!(expected, output); - - // Validate alternate formatting - let output_alternate = format!("{:#}", parsed); - assert_eq!(input, output_alternate); - } - - #[test] - fn test_invalid_input() { - let input = "(invalid"; - let result = parse_lino(input); - assert!(result.is_err()); - } -} \ No newline at end of file + use super::*; + + #[test] + fn test_simple_link() { + let input = "(1: 1 1)"; + let parsed = parse_str(input).expect("Failed to parse input"); + + // Validate regular formatting + let output = parsed.to_string(); + let expected = "((1: 1 1))"; // Expected regular output + assert_eq!(expected, output); + + // Validate alternate formatting + let output_alternate = format!("{:#}", parsed); + assert_eq!(input, output_alternate); + } + + #[test] + fn test_multiline_simple_links() { + let input = "(1: 1 1)\n(2: 2 2)"; + let parsed = parse_str(input).expect("Failed to parse input"); + + // Validate regular formatting + let output = parsed.to_string(); + let expected = "((1: 1 1) (2: 2 2))"; // Expected regular output + assert_eq!(expected, output); + + // Validate alternate formatting + let output_alternate = format!("{:#}", parsed); + assert_eq!(input, output_alternate); + } + + #[test] + fn test_link_with_source_target() { + let input = "(index: source target)"; + let parsed = parse_str(input).expect("Failed to parse input"); + + // Validate regular formatting + let output = parsed.to_string(); + let expected = "((index: source target))"; // Expected regular output + assert_eq!(expected, output); + + // Validate alternate formatting + let output_alternate = format!("{:#}", parsed); + assert_eq!(input, output_alternate); + } + + #[test] + fn test_link_with_source_type_target() { + let input = "(index: source type target)"; + let parsed = parse_str(input).expect("Failed to parse input"); + + // Validate regular formatting + let output = parsed.to_string(); + let expected = "((index: source type target))"; // Expected regular output + assert_eq!(expected, output); + + // Validate alternate formatting + let output_alternate = format!("{:#}", parsed); + assert_eq!(input, output_alternate); + } + + #[test] + fn test_is_ref() { + let reference = LiNo::Ref("some_value".to_string()); + assert!(reference.is_ref()); + assert!(!reference.is_seq()); + } + + #[test] + fn test_is_link() { + let link = LiNo::Seq { + id: Some("id".to_string()), + values: vec![LiNo::Ref("child".to_string())], + }; + assert!(link.is_seq()); + assert!(!link.is_ref()); + } + + #[test] + fn test_empty_link() { + let link = LiNo::Seq:: { id: None, values: vec![] }; + let output = link.to_string(); + assert_eq!(output, "()"); + } + + #[test] + fn test_nested_links() { + let input = "(1: (2: (3: 3)))"; + let parsed = parse_str(input).expect("Failed to parse input"); + + panic!("{:?}", parsed); + + // Validate regular formatting + let output = parsed.to_string(); + let expected = "((1: (2: (3: 3))))"; + assert_eq!(expected, output); + + // Validate alternate formatting + let output_alternate = format!("{:#}", parsed); + assert_eq!(input, output_alternate); + } + + #[test] + fn test_invalid_input() { + let input = "(invalid"; + let result = parse_str(input); + assert!(result.is_err()); + } +} diff --git a/rust/src/lino.rs b/rust/src/lino.rs new file mode 100644 index 0000000..a7aca01 --- /dev/null +++ b/rust/src/lino.rs @@ -0,0 +1,44 @@ +use std::fmt; + +#[derive(Debug, Clone)] +pub enum LiNo { + Ref(T), + Seq { id: Option, values: Vec }, +} + +impl LiNo { + pub fn is_ref(&self) -> bool { + matches!(self, LiNo::Ref(_)) + } + + pub fn is_seq(&self) -> bool { + matches!(self, LiNo::Seq { .. }) + } +} + +impl fmt::Display for LiNo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LiNo::Ref(value) => value.fmt(f), + LiNo::Seq { id, values } => { + let id = id.as_ref().map(|id| format!("{id}: ")).unwrap_or_default(); + + if f.alternate() { + let lines = values + .iter() + .map(|value| format!("{id}{value}")) + .collect::>() + .join("\n"); + write!(f, "{}", lines) + } else { + let values = values + .iter() + .map(ToString::to_string) + .collect::>() + .join(" "); + write!(f, "({id}{values})") + } + } + } + } +} diff --git a/rust/src/main.rs b/rust/src/main.rs index 9aad57a..f7b62a1 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,7 +1,7 @@ -use lino::lino::parse_lino; +use lino::parse_str; fn main() { - let notation = r#" + let notation = r#" (Type: Type Type) Number String @@ -9,12 +9,12 @@ fn main() { Value "#; - match parse_lino(notation) { - Ok(result) => { - println!("Parsed object:\n{:#?}", result); - let back_to_string = result.to_string(); // Преобразуем обратно в строку - println!("\nReconstructed notation:\n{}", back_to_string); - } - Err(error) => eprintln!("Error: {:?}", error), + match parse_str(notation) { + Ok(result) => { + println!("Parsed object:\n{:#?}", result); + let back_to_string = result.to_string(); + println!("\nReconstructed notation:\n{}", back_to_string); } -} \ No newline at end of file + Err(error) => eprintln!("Error: {:?}", error), + } +} diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..9fb196b --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,7 @@ +version = "Two" + +imports_granularity = "One" +use_small_heuristics = "Max" + +tab_spaces = 2 +max_width = 80 \ No newline at end of file