summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Cargo.lock1
-rw-r--r--pest_consume/Cargo.toml3
-rw-r--r--pest_consume/examples/csv/csv.pest15
-rw-r--r--pest_consume/examples/csv/main.rs64
-rw-r--r--pest_consume/src/lib.rs14
5 files changed, 97 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 017e1b2..82212fe 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -244,6 +244,7 @@ version = "0.1.0"
dependencies = [
"pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_consume_macros 0.1.0",
+ "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/pest_consume/Cargo.toml b/pest_consume/Cargo.toml
index 70bdd22..1e2b1af 100644
--- a/pest_consume/Cargo.toml
+++ b/pest_consume/Cargo.toml
@@ -12,3 +12,6 @@ repository = "https://github.com/Nadrieril/dhall-rust"
pest = "2.1"
proc-macro-hack = "0.5.9"
pest_consume_macros = { path = "../pest_consume_macros" }
+
+[dev-dependencies]
+pest_derive = "2.1"
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);
+}
diff --git a/pest_consume/src/lib.rs b/pest_consume/src/lib.rs
index 425d8cf..f14f6f5 100644
--- a/pest_consume/src/lib.rs
+++ b/pest_consume/src/lib.rs
@@ -1,3 +1,7 @@
+/// `pest_consume` extends [pest] to make it easy to consume the resulting pest parse tree.
+/// Given a grammar file, pest generates a parser that outputs an untyped parse tree. Then that
+/// parse tree needs to be transformed into whatever datastructures your application uses.
+/// `pest_consume` provides two powerful macros to make this easy.
use pest::error::Error;
use pest::Parser as PestParser;
use pest::RuleType;
@@ -85,6 +89,9 @@ mod node {
pub fn as_pair(&self) -> &Pair<'i, R> {
&self.pair
}
+ pub fn into_pair(self) -> Pair<'i, R> {
+ self.pair
+ }
pub fn as_span(&self) -> Span<'i> {
self.pair.as_span()
}
@@ -135,6 +142,13 @@ mod node {
{
Node::new(new_pair, self.user_data.clone())
}
+
+ pub fn as_pairs(&self) -> &Pairs<'i, R> {
+ &self.pairs
+ }
+ pub fn into_pairs(self) -> Pairs<'i, R> {
+ self.pairs
+ }
}
impl<'i, R, D> Iterator for Nodes<'i, R, D>