5 releases

0.3.4 Apr 16, 2023
0.3.3 Oct 31, 2018
0.3.2 Oct 31, 2018
0.3.1 Oct 31, 2018
0.3.0 Oct 31, 2018

#282 in Procedural macros

Download history 184/week @ 2023-12-14 160/week @ 2023-12-21 118/week @ 2023-12-28 294/week @ 2024-01-04 243/week @ 2024-01-11 235/week @ 2024-01-18 95/week @ 2024-01-25 133/week @ 2024-02-01 219/week @ 2024-02-08 193/week @ 2024-02-15 166/week @ 2024-02-22 204/week @ 2024-02-29 303/week @ 2024-03-07 252/week @ 2024-03-14 224/week @ 2024-03-21 374/week @ 2024-03-28

1,196 downloads per month
Used in 16 crates (8 directly)

MIT/Apache

34KB
612 lines

pest-ast

Convert from pest parse trees into typed syntax trees with ease!

Which would you rather have?

Pest Parse Tree
[
    Pair {
        rule: file,
        span: Span {
            str: "65279,1179403647,1463895090\n3.1415927,2.7182817,1.618034\n-40,-273.15\n13,42\n65537\n",
            start: 0,
            end: 81
        },
        inner: [
            Pair {
                rule: record,
                span: Span {
                    str: "65279,1179403647,1463895090",
                    start: 0,
                    end: 27
                },
                inner: [
                    Pair {
                        rule: field,
                        span: Span {
                            str: "65279",
                            start: 0,
                            end: 5
                        },
                        inner: []
                    },
                    Pair {
                        rule: field,
                        span: Span {
                            str: "1179403647",
                            start: 6,
                            end: 16
                        },
                        inner: []
                    },
                    Pair {
                        rule: field,
                        span: Span {
                            str: "1463895090",
                            start: 17,
                            end: 27
                        },
                        inner: []
                    }
                ]
            },
            Pair {
                rule: record,
                span: Span {
                    str: "3.1415927,2.7182817,1.618034",
                    start: 28,
                    end: 56
                },
                inner: [
                    Pair {
                        rule: field,
                        span: Span {
                            str: "3.1415927",
                            start: 28,
                            end: 37
                        },
                        inner: []
                    },
                    Pair {
                        rule: field,
                        span: Span {
                            str: "2.7182817",
                            start: 38,
                            end: 47
                        },
                        inner: []
                    },
                    Pair {
                        rule: field,
                        span: Span {
                            str: "1.618034",
                            start: 48,
                            end: 56
                        },
                        inner: []
                    }
                ]
            },
            Pair {
                rule: record,
                span: Span {
                    str: "-40,-273.15",
                    start: 57,
                    end: 68
                },
                inner: [
                    Pair {
                        rule: field,
                        span: Span {
                            str: "-40",
                            start: 57,
                            end: 60
                        },
                        inner: []
                    },
                    Pair {
                        rule: field,
                        span: Span {
                            str: "-273.15",
                            start: 61,
                            end: 68
                        },
                        inner: []
                    }
                ]
            },
            Pair {
                rule: record,
                span: Span {
                    str: "13,42",
                    start: 69,
                    end: 74
                },
                inner: [
                    Pair {
                        rule: field,
                        span: Span {
                            str: "13",
                            start: 69,
                            end: 71
                        },
                        inner: []
                    },
                    Pair {
                        rule: field,
                        span: Span {
                            str: "42",
                            start: 72,
                            end: 74
                        },
                        inner: []
                    }
                ]
            },
            Pair {
                rule: record,
                span: Span {
                    str: "65537",
                    start: 75,
                    end: 80
                },
                inner: [
                    Pair {
                        rule: field,
                        span: Span {
                            str: "65537",
                            start: 75,
                            end: 80
                        },
                        inner: []
                    }
                ]
            },
            Pair {
                rule: EOI,
                span: Span {
                    str: "",
                    start: 81,
                    end: 81
                },
                inner: []
            }
        ]
    }
]
Typed Syntax Tree
File {
    records: [
        Record {
            fields: [
                Field {
                    value: 65279.0
                },
                Field {
                    value: 1179403647.0
                },
                Field {
                    value: 1463895090.0
                }
            ]
        },
        Record {
            fields: [
                Field {
                    value: 3.1415927
                },
                Field {
                    value: 2.7182817
                },
                Field {
                    value: 1.618034
                }
            ]
        },
        Record {
            fields: [
                Field {
                    value: -40.0
                },
                Field {
                    value: -273.15
                }
            ]
        },
        Record {
            fields: [
                Field {
                    value: 13.0
                },
                Field {
                    value: 42.0
                }
            ]
        },
        Record {
            fields: [
                Field {
                    value: 65537.0
                }
            ]
        }
    ],
    eoi: EOI
}

The above parse tree is produced by the following pest grammar:

field = { (ASCII_DIGIT | "." | "-")+ }
record = { field ~ ("," ~ field)* }
file = { SOI ~ (record ~ ("\r\n" | "\n"))* ~ EOI }

parsing this csv:

65279,1179403647,1463895090
3.1415927,2.7182817,1.618034
-40,-273.15
13,42
65537

And converting it to a typed syntax tree is as simple as the following code:

mod ast {
    use super::csv::Rule;
    use pest::Span;

    fn span_into_str(span: Span) -> &str {
        span.as_str()
    }

    #[derive(Debug, FromPest)]
    #[pest_ast(rule(Rule::field))]
    pub struct Field {
        #[pest_ast(outer(with(span_into_str), with(str::parse), with(Result::unwrap)))]
        pub value: f64,
    }

    #[derive(Debug, FromPest)]
    #[pest_ast(rule(Rule::record))]
    pub struct Record {
        pub fields: Vec<Field>,
    }

    #[derive(Debug, FromPest)]
    #[pest_ast(rule(Rule::file))]
    pub struct File {
        pub records: Vec<Record>,
        eoi: EOI,
    }

    #[derive(Debug, FromPest)]
    #[pest_ast(rule(Rule::EOI))]
    struct EOI;
}

And doing the actual parse is as simple as

let mut parse_tree = csv::Parser::parse(csv::Rule::file, &source)?;
let syntax_tree = File::from_pest(&mut parse_tree).expect("infallible");

Dependencies

~0.6–1.1MB
~25K SLoC