extern crate alloc; use alloc::vec::Vec; use anyhow::Error; use core::{iter, result::Result}; use pest_typed::TypedParser; use pest_typed_derive::TypedParser; /// See https://datatracker.ietf.org/doc/html/rfc4180.html for CSV's format. #[derive(TypedParser)] #[grammar = "examples/csv.pest"] #[emit_rule_reference] struct Parser; fn main() -> Result<(), Error> { // Prepare input. Output syntax will depend on this. let input = "name,age\nTom,10\nJerry,20"; // Parser output. We may need some extra operations to make it into a table. let file = Parser::try_parse::(input)?; // Separate file by row. As pest don't have separator yet, this may be very common. // As `file` has 2 references to `row` in total, // return value type will also be a tuple with 2 elements. // Hide other rules, we'll get `row ~ (_ ~ row)* ~ _?`. // Therefore the return value type will be `(&row, Vec<&row>)`. let (first_row, following_rows) = file.row(); // Join rows as a single iterator. let rows = iter::once(first_row).chain(following_rows); // Sheet. let table = rows .map(|row| { // Separate each row by column. // Hide other rules, we'll get `item ~ (_ ~ item)*`. // Therefore the return value type will be `(&item, Vec<&item>)`. let (first_item, following_items) = row.item(); // Join columns as a single iterator. let items = iter::once(first_item).chain(following_items); // Extract string from each cell. let row = items.map(|cell| cell.span.as_str()).collect::>(); row }) .collect::>(); // Recover input from sheet. let recovered = table .into_iter() .map(|row| row.join(",")) .collect::>() .join("\n"); assert_eq!(recovered, input); Ok(()) }