diff options
Diffstat (limited to 'pest_consume/examples')
-rw-r--r-- | pest_consume/examples/csv/csv.pest | 15 | ||||
-rw-r--r-- | pest_consume/examples/csv/main.rs | 64 |
2 files changed, 79 insertions, 0 deletions
diff --git a/pest_consume/examples/csv/csv.pest b/pest_consume/examples/csv/csv.pest new file mode 100644 index 0000000..a67af8c --- /dev/null +++ b/pest_consume/examples/csv/csv.pest @@ -0,0 +1,15 @@ +WHITESPACE = _{ " "+ } +newline = _{ "\r\n" | "\n" } +number = { "-"? ~ (ASCII_DIGIT | ".")+ } +string = { (!"'" ~ ASCII)* } +field = ${ + number + | "'" ~ string ~ "'" +} +record = { + field ~ ("," ~ field)* + | "" +} +file = { + SOI ~ record ~ (newline ~ record)* ~ newline? ~ EOI +} diff --git a/pest_consume/examples/csv/main.rs b/pest_consume/examples/csv/main.rs new file mode 100644 index 0000000..037948b --- /dev/null +++ b/pest_consume/examples/csv/main.rs @@ -0,0 +1,64 @@ +#![feature(slice_patterns)] +use pest_consume::{match_inputs, Parser}; + +#[derive(pest_derive::Parser)] +#[grammar = "../examples/csv/csv.pest"] +struct CSVParser; + +type ParseResult<T> = Result<T, pest::error::Error<Rule>>; +type Node<'i> = pest_consume::Node<'i, Rule, ()>; + +#[derive(Debug)] +enum CSVField<'a> { + Number(f64), + String(&'a str), +} + +type CSVRecord<'a> = Vec<CSVField<'a>>; +type CSVFile<'a> = Vec<CSVRecord<'a>>; + +#[pest_consume::parser(CSVParser, Rule)] +impl CSVParser { + fn EOI(_input: Node) -> ParseResult<()> { + Ok(()) + } + + fn number(input: Node) -> ParseResult<f64> { + Ok(input.as_str().parse().unwrap()) + } + + fn string(input: Node) -> ParseResult<&str> { + Ok(input.as_str()) + } + + fn field(input: Node) -> ParseResult<CSVField> { + Ok(match_inputs!(input.children(); + [number(n)] => CSVField::Number(n), + [string(s)] => CSVField::String(s), + )) + } + + fn record(input: Node) -> ParseResult<CSVRecord> { + Ok(match_inputs!(input.children(); + [field(fields)..] => fields.collect(), + )) + } + + fn file(input: Node) -> ParseResult<CSVFile> { + Ok(match_inputs!(input.children(); + [record(records).., EOI(_)] => records.collect(), + )) + } +} + +fn parse_csv(input_str: &str) -> ParseResult<CSVFile> { + let inputs = CSVParser::parse(Rule::file, input_str)?; + Ok(match_inputs!(<CSVParser>; inputs; + [file(e)] => e, + )) +} + +fn main() { + let parsed = parse_csv("-273.15, ' a string '\n\n42, 0"); + println!("{:?}", parsed); +} |