Introduces a custom error type for the SPARQL parser

The SPARQL parser and algebra does not directly depends now on the other parts of Oxigraph outside of the RDF model
pull/35/head
Tpt 5 years ago
parent 06757ed470
commit 2866e1e3bd
  1. 7
      lib/src/error.rs
  2. 23
      lib/src/sparql/mod.rs
  3. 93
      lib/src/sparql/parser.rs

@ -1,7 +1,6 @@
use crate::sparql::SparqlParseError;
use oxilangtag::LanguageTagParseError;
use oxiri::IriParseError;
use peg::error::ParseError;
use peg::str::LineCol;
use rio_turtle::TurtleError;
use rio_xml::RdfXmlError;
use std::error;
@ -120,8 +119,8 @@ impl From<quick_xml::Error> for Error {
}
}
impl From<ParseError<LineCol>> for Error {
fn from(error: ParseError<LineCol>) -> Self {
impl From<SparqlParseError> for Error {
fn from(error: SparqlParseError) -> Self {
Self::wrap(error)
}
}

@ -12,7 +12,6 @@ mod xml_results;
use crate::model::NamedNode;
use crate::sparql::algebra::QueryVariants;
use crate::sparql::eval::SimpleEvaluator;
use crate::sparql::parser::read_sparql_query;
use crate::sparql::plan::TripleTemplate;
use crate::sparql::plan::{DatasetView, PlanNode};
use crate::sparql::plan_builder::PlanBuilder;
@ -20,13 +19,14 @@ use crate::store::ReadableEncodedStore;
use crate::Error;
use crate::Result;
use oxiri::Iri;
use std::fmt;
pub use crate::sparql::algebra::GraphPattern;
pub use crate::sparql::model::BindingsIterator;
pub use crate::sparql::model::QueryResult;
pub use crate::sparql::model::QueryResultSyntax;
pub use crate::sparql::model::Variable;
pub use crate::sparql::parser::Query;
pub use crate::sparql::parser::SparqlParseError;
/// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/)
pub trait PreparedQuery {
@ -61,7 +61,7 @@ enum SimplePreparedQueryAction<S: ReadableEncodedStore> {
impl<'a, S: ReadableEncodedStore + 'a> SimplePreparedQuery<S> {
pub(crate) fn new(store: S, query: &str, options: QueryOptions<'_>) -> Result<Self> {
let dataset = DatasetView::new(store, options.default_graph_as_union);
Ok(Self(match read_sparql_query(query, options.base_iri)? {
Ok(Self(match Query::parse(query, options.base_iri)?.0 {
QueryVariants::Select {
algebra, base_iri, ..
} => {
@ -219,20 +219,3 @@ impl<'a> QueryOptions<'a> {
self
}
}
/// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/)
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Query(QueryVariants);
impl fmt::Display for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl Query {
/// Parses a SPARQL query
pub fn parse(query: &str, base_iri: Option<&str>) -> Result<Self> {
Ok(Query(read_sparql_query(query, base_iri)?))
}
}

@ -4,13 +4,80 @@ use crate::model::*;
use crate::sparql::algebra::*;
use crate::sparql::model::*;
use oxiri::{Iri, IriParseError};
use peg::error::ParseError;
use peg::parser;
use peg::str::LineCol;
use std::borrow::Cow;
use std::char;
use std::collections::HashMap;
use std::collections::{BTreeMap, BTreeSet};
use std::error::Error;
use std::str::Chars;
use std::str::FromStr;
use std::{char, fmt};
/// A parsed [SPARQL query](https://www.w3.org/TR/sparql11-query/)
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Query(pub(crate) QueryVariants);
impl fmt::Display for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl Query {
/// Parses a SPARQL query
pub fn parse(query: &str, base_iri: Option<&str>) -> Result<Self, SparqlParseError> {
let mut state = ParserState {
base_iri: if let Some(base_iri) = base_iri {
Some(
Iri::parse(base_iri.to_owned()).map_err(|e| SparqlParseError {
inner: SparqlParseErrorKind::InvalidBaseIri(e),
})?,
)
} else {
None
},
namespaces: HashMap::default(),
bnodes_map: BTreeMap::default(),
used_bnodes: BTreeSet::default(),
aggregations: Vec::default(),
};
Ok(Self(
parser::QueryUnit(&unescape_unicode_codepoints(query), &mut state).map_err(|e| {
SparqlParseError {
inner: SparqlParseErrorKind::Parser(e),
}
})?,
))
}
}
/// Error returned during SPARQL parsing.
#[derive(Debug)]
pub struct SparqlParseError {
inner: SparqlParseErrorKind,
}
#[derive(Debug)]
enum SparqlParseErrorKind {
InvalidBaseIri(IriParseError),
Parser(ParseError<LineCol>),
}
impl fmt::Display for SparqlParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
SparqlParseErrorKind::InvalidBaseIri(e) => {
write!(f, "Invalid SPARQL base IRI provided: {}", e)
}
SparqlParseErrorKind::Parser(e) => e.fmt(f),
}
}
}
impl Error for SparqlParseError {}
struct FocusedTriplePattern<F> {
focus: F,
@ -521,30 +588,6 @@ pub fn unescape_pn_local(input: &str) -> Cow<'_, str> {
unescape_characters(input, &UNESCAPE_PN_CHARACTERS, &UNESCAPE_PN_REPLACEMENT)
}
//include!(concat!(env!("OUT_DIR"), "/sparql_grammar.rs"));
pub fn read_sparql_query(
query: &str,
base_iri: Option<&str>,
) -> super::super::Result<QueryVariants> {
let mut state = ParserState {
base_iri: if let Some(base_iri) = base_iri {
Some(Iri::parse(base_iri.to_owned())?)
} else {
None
},
namespaces: HashMap::default(),
bnodes_map: BTreeMap::default(),
used_bnodes: BTreeSet::default(),
aggregations: Vec::default(),
};
Ok(parser::QueryUnit(
&unescape_unicode_codepoints(query),
&mut state,
)?)
}
parser! {
//See https://www.w3.org/TR/turtle/#sec-grammar
grammar parser(state: &mut ParserState) for str {

Loading…
Cancel
Save