pub fn parser() -> BoxedParser<'static, Token, Program, Simple<Token>> {
    use Token::*;

    let ident = select! { Ident(id) => id };

    let literal = select! {
        Number(n) => Literal::Number(n),
        String(s) => Literal::String(s),
        Ident(b) if b == "true" => Literal::Boolean(true),
        Ident(b) if b == "false" => Literal::Boolean(false),
    }
    .labelled("literal");

    // Declared here so that we can use it for aggregate subqueries.
    let mut clauses = Recursive::<_, Vec<Clause>, Simple<Token>>::declare();

    let value = recursive(|value| {
        let aggregate = ident
            .then(value.delimited_by(Ctrl("["), Ctrl("]")))
            .then(clauses.clone().delimited_by(Ctrl("{"), Ctrl("}")))
            .map(|((operator, value), subquery)| Aggregate {
                operator,
                value: Box::new(value),
                subquery,
            });

        choice((
            aggregate.map(Value::Aggregate),
            literal.map(Value::Literal),
            select! {
                Expr(e) => Value::Expr(e),
                Ident(id) => Value::Id(id),
            },
        ))
        .labelled("value")
    });

    let prop = ident
        .then(just(Ctrl(":")).ignore_then(value.clone()).or_not())
        .try_map(|(id, value), span| {
            let value = value.unwrap_or_else(|| Value::Id(id.clone()));
            match &value {
                Value::Id(name) if is_reserved_word(name) => Err(Simple::custom(
                    span,
                    "Cannot use reserved word as a variable binding",
                )),
                _ => Ok((id, value)),
            }
        })
        .labelled("prop");

    let fact = ident
        .then(
            prop.separated_by(just(Ctrl(",")))
                .delimited_by(Ctrl("("), Ctrl(")")),
        )
        .map(|(name, props)| Fact {
            name,
            props: props.into_iter().collect(),
        })
        .labelled("fact");

    let expr = select! { Expr(e) => e };

    let binding = ident
        .then_ignore(just(Ctrl("=")))
        .then(value)
        .labelled("binding");

    let clause = choice((
        fact.clone().map(Clause::Fact),
        expr.map(Clause::Expr),
        binding.map(|(name, value)| Clause::Binding(name, value)),
    ))
    .labelled("clause");

    clauses.define(clause.clone().separated_by(just(Ctrl(","))));

    let rule = fact
        .then(
            just(Ctrl(":-"))
                .ignore_then(clauses)
                .then_ignore(just(Ctrl(".")))
                .try_map(|clauses, span| {
                    if clauses.is_empty() {
                        Err(Simple::custom(span, "Rule needs at least one clause"))
                    } else {
                        Ok(clauses)
                    }
                })
                .or(just(Ctrl(".")).to(Vec::new())),
        )
        .map(|(goal, clauses)| Rule { goal, clauses })
        .labelled("rule");

    let import = select! { Ident(k) if k == "import" => () }
        .ignore_then(ident)
        .then_ignore(select! { Ident(k) if k == "from" => () })
        .then(select! { String(s) => s })
        .map(|(name, uri)| Import { name, uri });

    enum Entry {
        Rule(Rule),
        Import(Import),
    }

    let program = choice((rule.map(Entry::Rule), import.map(Entry::Import)))
        .repeated()
        .map(|entries| {
            let mut rules = Vec::new();
            let mut imports = Vec::new();
            for entry in entries {
                match entry {
                    Entry::Rule(rule) => rules.push(rule),
                    Entry::Import(import) => imports.push(import),
                }
            }
            Program { rules, imports }
        });

    program.then_ignore(end()).boxed()
}
/// Construct a parser combinator for syntactic analysis (stage 2).
///
/// If possible, prefer to use the higher-level `Grammar` API directly, rather
/// than this low-level implementation of a parser combinator.
Construct a parser combinator for syntactic analysis (stage 2).
If possible, prefer to use the higher-level `Grammar` API directly, rather
than this low-level implementation of a parser combinator.
Construct a parser combinator for syntactic analysis ( stage 2 ) . If possible prefer to use the higher - level ` Grammar ` API directly rather than this low - level implementation of a parser combinator .
pub fn parser() -> BoxedParser<'static, Token, Program, Simple<Token>> {
    use Token::*;
    let ident = select! { Ident(id) => id };
    let literal = select! {
        Number(n) => Literal::Number(n),
        String(s) => Literal::String(s),
        Ident(b) if b == "true" => Literal::Boolean(true),
        Ident(b) if b == "false" => Literal::Boolean(false),
    }
    .labelled("literal");
    // Declared here so that we can use it for aggregate subqueries.
    let mut clauses = Recursive::<_, Vec<Clause>, Simple<Token>>::declare();
    let value = recursive(|value| {
        let aggregate = ident
            .then(value.delimited_by(Ctrl("["), Ctrl("]")))
            .then(clauses.clone().delimited_by(Ctrl("{"), Ctrl("}")))
            .map(|((operator, value), subquery)| Aggregate {
                operator,
                value: Box::new(value),
                subquery,
            });
        choice((
            aggregate.map(Value::Aggregate),
            literal.map(Value::Literal),
            select! {
                Expr(e) => Value::Expr(e),
                Ident(id) => Value::Id(id),
            },
        ))
        .labelled("value")
    });
    let prop = ident
        .then(just(Ctrl(":")).ignore_then(value.clone()).or_not())
        .try_map(|(id, value), span| {
            let value = value.unwrap_or_else(|| Value::Id(id.clone()));
            match &value {
                Value::Id(name) if is_reserved_word(name) => Err(Simple::custom(
                    span,
                    "Cannot use reserved word as a variable binding",
                )),
                _ => Ok((id, value)),
            }
        })
        .labelled("prop");
    let fact = ident
        .then(
            prop.separated_by(just(Ctrl(",")))
                .delimited_by(Ctrl("("), Ctrl(")")),
        )
        .map(|(name, props)| Fact {
            name,
            props: props.into_iter().collect(),
        })
        .labelled("fact");
    let expr = select! { Expr(e) => e };
    let binding = ident
        .then_ignore(just(Ctrl("=")))
        .then(value)
        .labelled("binding");
    let clause = choice((
        fact.clone().map(Clause::Fact),
        expr.map(Clause::Expr),
        binding.map(|(name, value)| Clause::Binding(name, value)),
    ))
    .labelled("clause");
    clauses.define(clause.clone().separated_by(just(Ctrl(","))));
    let rule = fact
        .then(
            just(Ctrl(":-"))
                .ignore_then(clauses)
                .then_ignore(just(Ctrl(".")))
                .try_map(|clauses, span| {
                    if clauses.is_empty() {
                        Err(Simple::custom(span, "Rule needs at least one clause"))
                    } else {
                        Ok(clauses)
                    }
                })
                .or(just(Ctrl(".")).to(Vec::new())),
        )
        .map(|(goal, clauses)| Rule { goal, clauses })
        .labelled("rule");
    let import = select! { Ident(k) if k == "import" => () }
        .ignore_then(ident)
        .then_ignore(select! { Ident(k) if k == "from" => () })
        .then(select! { String(s) => s })
        .map(|(name, uri)| Import { name, uri });
    enum Entry {
        Rule(Rule),
        Import(Import),
    }
    let program = choice((rule.map(Entry::Rule), import.map(Entry::Import)))
        .repeated()
        .map(|entries| {
            let mut rules = Vec::new();
            let mut imports = Vec::new();
            for entry in entries {
                match entry {
                    Entry::Rule(rule) => rules.push(rule),
                    Entry::Import(import) => imports.push(import),
                }
            }
            Program { rules, imports }
        });
    program.then_ignore(end()).boxed()
}
pub fn parser ( ) -> BoxedParser < ' static , Token , Program , Simple < Token > > { use Token :: * ; let ident = select ! { Ident ( id ) id } ; let literal = select ! { Number ( n ) Literal Number ( n ) String ( s ) Literal String ( s ) Ident ( b ) if b " " Literal Boolean ( true ) Ident ( b ) if b " " Literal Boolean ( false ) } . labelled ( " " ) ; // Declared here so that we can use it for aggregate subqueries. let mut clauses = Recursive :: < _ , Vec < Clause > , Simple < Token > > :: declare ( ) ; let value = recursive ( | value | { let aggregate = ident . then ( value . delimited_by ( Ctrl ( " " ) , Ctrl ( " " ) ) ) . then ( clauses . clone ( ) . delimited_by ( Ctrl ( " " ) , Ctrl ( " " ) ) ) . map ( | ( ( operator , value ) , subquery ) | Aggregate { operator , value : Box :: new ( value ) , subquery , } ) ; choice ( ( aggregate . map ( Value :: Aggregate ) , literal . map ( Value :: Literal ) , select ! { Expr ( e ) Value Expr ( e ) Ident ( id ) Value Id ( id ) } , ) ) . labelled ( " " ) } ) ; let prop = ident . then ( just ( Ctrl ( " " ) ) . ignore_then ( value . clone ( ) ) . or_not ( ) ) . try_map ( | ( id , value ) , span | { let value = value . unwrap_or_else ( | | Value :: Id ( id . clone ( ) ) ) ; match & value { Value :: Id ( name ) if is_reserved_word ( name ) => Err ( Simple :: custom ( span , " " , ) ) , _ => Ok ( ( id , value ) ) , } } ) . labelled ( " " ) ; let fact = ident . then ( prop . separated_by ( just ( Ctrl ( " " ) ) ) . delimited_by ( Ctrl ( " " ) , Ctrl ( " " ) ) , ) . map ( | ( name , props ) | Fact { name , props : props . into_iter ( ) . collect ( ) , } ) . labelled ( " " ) ; let expr = select ! { Expr ( e ) e } ; let binding = ident . then_ignore ( just ( Ctrl ( " " ) ) ) . then ( value ) . labelled ( " " ) ; let clause = choice ( ( fact . clone ( ) . map ( Clause :: Fact ) , expr . map ( Clause :: Expr ) , binding . map ( | ( name , value ) | Clause :: Binding ( name , value ) ) , ) ) . labelled ( " " ) ; clauses . define ( clause . clone ( ) . separated_by ( just ( Ctrl ( " " ) ) ) ) ; let rule = fact . then ( just ( Ctrl ( " " ) ) . ignore_then ( clauses ) . then_ignore ( just ( Ctrl ( " " ) ) ) . try_map ( | clauses , span | { if clauses . is_empty ( ) { Err ( Simple :: custom ( span , " " ) ) } else { Ok ( clauses ) } } ) . or ( just ( Ctrl ( " " ) ) . to ( Vec :: new ( ) ) ) , ) . map ( | ( goal , clauses ) | Rule { goal , clauses } ) . labelled ( " " ) ; let import = select ! { Ident ( k ) if k " " ( ) } . ignore_then ( ident ) . then_ignore ( select ! { Ident ( k ) if k " " ( ) } ) . then ( select ! { String ( s ) s } ) . map ( | ( name , uri ) | Import { name , uri } ) ; enum Entry { Rule ( Rule ) , Import ( Import ) , } let program = choice ( ( rule . map ( Entry :: Rule ) , import . map ( Entry :: Import ) ) ) . repeated ( ) . map ( | entries | { let mut rules = Vec :: new ( ) ; let mut imports = Vec :: new ( ) ; for entry in entries { match entry { Entry :: Rule ( rule ) => rules . push ( rule ) , Entry :: Import ( import ) => imports . push ( import ) , } } Program { rules , imports } } ) ; program . then_ignore ( end ( ) ) . boxed ( ) }
Construct a parser combinator for syntactic analysis (stage 2).
Construct a parser combinator for syntactic analysis ( stage 2 ) .