tortank 0.30.7

Turtle/N3 parser
Documentation
use std::collections::VecDeque;

use nom_language::error::VerboseError;

use crate::prelude::*;

use crate::shared::RDF_NIL;

use crate::triple_common_parser::iri::iri;
use crate::triple_common_parser::literal::literal_turtle as literal;
use crate::triple_common_parser::prologue::{
    base_sparql, base_turtle, prefix_sparql, prefix_turtle,
};
use crate::triple_common_parser::triple::{
    anon_bnode, collection, labeled_bnode, ns_type, object_list, predicate_list,
};
use crate::triple_common_parser::{BlankNode, Iri, Literal, comments};

#[derive(PartialEq, Debug)]
pub enum TurtleValue<'a> {
    Base(Iri<'a>),
    Prefix((&'a str, Iri<'a>)),
    Iri(Iri<'a>),
    Literal(Literal<'a>),
    BNode(BlankNode<'a>),
    ObjectList(Vec<TurtleValue<'a>>),
    Collection(VecDeque<TurtleValue<'a>>),
    PredicateObject {
        predicate: Box<TurtleValue<'a>>,
        object: Box<TurtleValue<'a>>,
    },
    Statement {
        subject: Box<TurtleValue<'a>>,
        predicate_objects: Vec<TurtleValue<'a>>,
    },
}

fn object_lists(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    object_list(object, TurtleValue::ObjectList).parse(s)
}

fn predicate_lists<'a, F>(
    subject_extractor: F,
) -> impl Parser<&'a str, Output = TurtleValue<'a>, Error = VerboseError<&'a str>>
where
    F: Fn(&'a str) -> ParserResult<'a, TurtleValue<'a>>,
{
    let map_predicate_object = |(predicate, objects)| TurtleValue::PredicateObject {
        predicate: Box::new(predicate),
        object: Box::new(objects),
    };
    predicate_list(
        subject_extractor,
        predicate,
        object_lists,
        map_predicate_object,
        |subject, list| TurtleValue::Statement {
            subject: Box::new(subject),
            predicate_objects: list,
        },
    )
}

fn collection_turtle(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    map(collection(object), |res: VecDeque<TurtleValue>| {
        if res.is_empty() {
            TurtleValue::Iri(Iri::Enclosed(RDF_NIL))
        } else {
            TurtleValue::Collection(res)
        }
    })
    .parse(s)
}

fn anon_bnode_turtle(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    let unlabeled_subject = |s| Ok((s, TurtleValue::BNode(BlankNode::Unlabeled)));
    anon_bnode(alt((predicate_lists(unlabeled_subject), unlabeled_subject))).parse(s)
}

fn blank_node(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    alt((map(labeled_bnode, TurtleValue::BNode), anon_bnode_turtle)).parse(s)
}

fn iri_turtle(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    map(iri, TurtleValue::Iri).parse(s)
}
fn literal_turtle(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    map(literal, TurtleValue::Literal).parse(s)
}

pub(crate) fn subject(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    alt((blank_node, iri_turtle, collection_turtle)).parse(s)
}
pub(crate) fn predicate(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    alt((map(ns_type, TurtleValue::Iri), iri_turtle)).parse(s)
}

pub(crate) fn object(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    preceded(
        multispace0,
        alt((iri_turtle, blank_node, collection_turtle, literal_turtle)),
    )
    .parse(s)
}

pub(crate) fn triples(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    terminated(
        alt((predicate_lists(subject), anon_bnode_turtle)),
        preceded(multispace0, terminated(alt((tag("."), eof)), multispace0)),
    )
    .parse(s)
}

pub(crate) fn ntriple_statement(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    preceded(
        comments,
        terminated(
            map(
                (ntriple_subject, ntriple_predicate, ntriple_object),
                |(s, p, o)| TurtleValue::Statement {
                    subject: Box::new(s),
                    predicate_objects: vec![TurtleValue::PredicateObject {
                        predicate: Box::new(p),
                        object: Box::new(o),
                    }],
                },
            ),
            preceded(multispace0, terminated(alt((tag("."), eof)), multispace0)),
        ),
    )
    .parse(s)
}
pub(crate) fn ntriple_subject(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    alt((map(labeled_bnode, TurtleValue::BNode), iri_turtle)).parse(s)
}
pub(crate) fn ntriple_predicate(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    alt((map(ns_type, TurtleValue::Iri), iri_turtle)).parse(s)
}

pub(crate) fn ntriple_object(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    preceded(
        multispace0,
        alt((
            iri_turtle,
            map(labeled_bnode, TurtleValue::BNode),
            literal_turtle,
        )),
    )
    .parse(s)
}

fn directive(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    let base_to_turtle = map(alt((base_sparql, base_turtle)), TurtleValue::Base);
    let prefix_to_turtle = map(alt((prefix_turtle, prefix_sparql)), TurtleValue::Prefix);
    alt((base_to_turtle, prefix_to_turtle)).parse(s)
}

pub(crate) fn statement(s: &'_ str) -> ParserResult<'_, TurtleValue<'_>> {
    preceded(comments, alt((directive, triples))).parse(s)
}

pub fn statements(s: &'_ str) -> ParserResult<'_, Vec<TurtleValue<'_>>> {
    many0(statement).parse(s)
}