Function neure::re::ctor::rec_parser

source ·
pub fn rec_parser<'a, 'b, C, O, I>(
    handler: impl Fn(RecursiveCtor<'b, C, O>) -> I
) -> RecursiveCtor<'b, C, O>where
    C: Context<'a>,
    I: Fn(&mut C) -> Result<O, Error> + 'b,
Expand description

Example

    #[derive(Debug, PartialEq, Eq)]
    enum Xml {
        Element { name: String, child: Vec<Xml> },
        Enclosed(String),
    }

    pub fn parser<'a: 'b, 'b>(
        ctor: RecursiveCtor<'b, CharsCtx<'a>, Vec<Xml>>,
    ) -> impl Fn(&mut CharsCtx<'a>) -> Result<Vec<Xml>, Error> + 'b {
        move |ctx| {
            let alpha = neu::alphabetic()
                .repeat_full()
                .map(|v: &str| Ok(v.to_string()));
            let s = alpha.quote("<", ">");
            let e = alpha.quote("</", ">");
            let c = alpha.quote("<", "/>").map(|v| Ok(Xml::Enclosed(v)));
            let m = |((l, c), r): ((String, Vec<Xml>), String)| {
                if l != r {
                    Err(Error::Uid(0))
                } else {
                    Ok(Xml::Element { name: l, child: c })
                }
            };

            ctx.ctor(&s.then(ctor.clone()).then(e).map(m).or(c).repeat(1..))
        }
    }
    let xml = rec_parser(parser);
    let ret = CharsCtx::new("<language><rust><linux/></rust><cpp><windows/></cpp></language>")
        .ctor(&xml)?;
    let chk = vec![Xml::Element {
        name: "language".to_owned(),
        child: vec![
            Xml::Element {
                name: "rust".to_owned(),
                child: vec![Xml::Enclosed("linux".to_owned())],
            },
            Xml::Element {
                name: "cpp".to_owned(),
                child: vec![Xml::Enclosed("windows".to_owned())],
            },
        ],
    }];

    assert_eq!(ret, chk);
    Ok(())