6 releases

new 0.3.5 Dec 20, 2024
0.3.4 Apr 16, 2023
0.3.3 Oct 31, 2018

#971 in Procedural macros

Download history 247/week @ 2024-08-30 254/week @ 2024-09-06 195/week @ 2024-09-13 227/week @ 2024-09-20 193/week @ 2024-09-27 91/week @ 2024-10-04 163/week @ 2024-10-11 216/week @ 2024-10-18 224/week @ 2024-10-25 329/week @ 2024-11-01 116/week @ 2024-11-08 155/week @ 2024-11-15 193/week @ 2024-11-22 204/week @ 2024-11-29 327/week @ 2024-12-06 325/week @ 2024-12-13

1,064 downloads per month
Used in 17 crates (9 directly)

MIT/Apache

34KB
610 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–1MB
~24K SLoC