From 359c46d77642572e708472e4a224b7adc55db900 Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Fri, 19 May 2023 12:56:38 -0700 Subject: [PATCH] Implement pest CSV demo https://pest.rs/book/examples/csv.html --- Cargo.toml | 2 ++ demo/demo.csv | 5 +++++ demo/src/main.rs | 2 +- src/csv.pest | 9 +++++++++ src/lib.rs | 36 ++++++++++++++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 demo/demo.csv create mode 100644 src/csv.pest diff --git a/Cargo.toml b/Cargo.toml index 1bcc56a..e250776 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +pest = "2.6.0" +pest_derive = "2.6.0" diff --git a/demo/demo.csv b/demo/demo.csv new file mode 100644 index 0000000..20a98c9 --- /dev/null +++ b/demo/demo.csv @@ -0,0 +1,5 @@ +65279,1179403647,1463895090 +3.1415927,2.7182817,1.618034 +-40,-273.15 +13,42 +65537 diff --git a/demo/src/main.rs b/demo/src/main.rs index 265c3f7..79ef2ea 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -1,5 +1,5 @@ use renrs; fn main() { - renrs::hello(); + renrs::parse("demo.csv"); } diff --git a/src/csv.pest b/src/csv.pest new file mode 100644 index 0000000..8b94fc7 --- /dev/null +++ b/src/csv.pest @@ -0,0 +1,9 @@ +// + indicates one or more times +field = { (ASCII_DIGIT | "." | "-")+ } +// ~ indicates directly followed by +// * indicates zero or more times (optional) +record = { field ~ ("," ~ field)* } +// SOI - start of input +// END - end of input +// There may be trailing newlines at the end +file = { SOI ~ (record ~ ("\r\n" | "\n"))* ~ "\n"* ~ EOI } diff --git a/src/lib.rs b/src/lib.rs index fda8464..6b32541 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,35 @@ -pub fn hello() { - println!("Hello, world!"); +use std::fs; + +use pest::Parser; +use pest_derive::Parser; + +#[derive(Parser)] +#[grammar = "csv.pest"] +struct CSVParser; + +pub fn parse(file_path: &str) { + let unparsed_file = fs::read_to_string(file_path).expect("cannot find file"); + let file = CSVParser::parse(Rule::file, &unparsed_file) + .expect("unsuccessful parse") // unwrap the parse result + .next().unwrap(); // get and unwrap the `file` rule; never fails + + let mut field_sum = 0.0; + let mut record_count: u64 = 0; + + for record in file.into_inner() { + match record.as_rule() { + Rule::record => { + record_count += 1; + + for field in record.into_inner() { + field_sum += field.as_str().parse::().unwrap(); + } + }, + Rule::EOI => (), + _ => unreachable!(), + } + } + + println!("Sum of fields: {field_sum}"); + println!("Number of records: {record_count}"); }