private void TryParseTriple(XmlReader reader, IRdfHandler handler, Uri graphUri) { //Verify Node Name if (!reader.Name.Equals("triple")) { throw Error("Unexpected Element <" + reader.Name + "> encountered, only an optional <id>/<uri> element followed by zero/more <triple> elements are permitted within a <graph> element", reader); } //Parse XML Nodes into RDF Nodes INode subj, pred, obj; subj = this.TryParseNode(reader, handler, TripleSegment.Subject); pred = this.TryParseNode(reader, handler, TripleSegment.Predicate); obj = this.TryParseNode(reader, handler, TripleSegment.Object); if (reader.NodeType != XmlNodeType.EndElement) { throw Error("Unexpected element type " + reader.NodeType.ToString() + " encountered, expected the </triple> element", reader); } if (!reader.Name.Equals("triple")) { throw Error("Unexpected </" + reader.Name + "> encountered, expected a </triple> element", reader); } //Assert the resulting Triple if (!handler.HandleTriple(new Triple(subj, pred, obj, graphUri))) { ParserHelper.Stop(); } }
private void TryParseTriple(IRdfHandler handler, IToken s, IToken p, IToken o, Uri graphUri) { INode subj, pred, obj; switch (s.TokenType) { case Token.BLANKNODEWITHID: subj = handler.CreateBlankNode(s.Value.Substring(2)); break; case Token.URI: subj = ParserHelper.TryResolveUri(handler, s); break; default: throw ParserHelper.Error("Unexpected Token '" + s.GetType().ToString() + "' encountered, expected a Blank Node/URI as the Subject of a Triple", s); } switch (p.TokenType) { case Token.URI: pred = ParserHelper.TryResolveUri(handler, p); break; default: throw ParserHelper.Error("Unexpected Token '" + p.GetType().ToString() + "' encountered, expected a URI as the Predicate of a Triple", p); } switch (o.TokenType) { case Token.BLANKNODEWITHID: obj = handler.CreateBlankNode(o.Value.Substring(2)); break; case Token.LITERAL: obj = handler.CreateLiteralNode(o.Value); break; case Token.LITERALWITHDT: String dtUri = ((LiteralWithDataTypeToken)o).DataType; obj = handler.CreateLiteralNode(o.Value, new Uri(dtUri.Substring(1, dtUri.Length - 2))); break; case Token.LITERALWITHLANG: obj = handler.CreateLiteralNode(o.Value, ((LiteralWithLanguageSpecifierToken)o).Language); break; case Token.URI: obj = ParserHelper.TryResolveUri(handler, o); break; default: throw ParserHelper.Error("Unexpected Token '" + o.GetType().ToString() + "' encountered, expected a Blank Node/Literal/URI as the Object of a Triple", o); } if (!handler.HandleTriple(new Triple(subj, pred, obj, graphUri))) { ParserHelper.Stop(); } }
private void TryParseHeaderRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); bool allowEOL = true, expectComma = false; while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.EOL: if (allowEOL) { break; } else { throw ParserHelper.Error("Unexpected End of Line, expected a Variable", next); } case Token.PLAINLITERAL: case Token.LITERAL: if (expectComma) { throw ParserHelper.Error("Unexpected Variable, expected a comma between each Variable", next); } context.Variables.Add(next.Value); if (!context.Handler.HandleVariable(next.Value)) { ParserHelper.Stop(); } allowEOL = true; expectComma = true; break; case Token.COMMA: expectComma = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) { throw ParserHelper.Error("Unexpected EOF, expected another Variable for the Header Row", next); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } // Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) { break; } } }
private void TryParseDirective(TriGParserContext context) { //See what type of directive it is IToken directive = context.Tokens.Dequeue(); if (directive.TokenType == Token.BASEDIRECTIVE) { //Base Directives Invalid in TriG throw ParserHelper.Error("The Base Directive is not a valid in TriG", directive); } else if (directive.TokenType == Token.PREFIXDIRECTIVE) { //Prefix Directive IToken prefix = context.Tokens.Dequeue(); if (prefix.TokenType == Token.PREFIX) { IToken uri = context.Tokens.Dequeue(); if (uri.TokenType == Token.URI) { //Ensure the Uri is absolute try { Uri u = new Uri(uri.Value, UriKind.Absolute); String pre = (prefix.Value.Equals(":")) ? String.Empty : prefix.Value.Substring(0, prefix.Value.Length - 1); context.Namespaces.AddNamespace(pre, u); if (!context.Handler.HandleNamespace(pre, u)) { ParserHelper.Stop(); } //Expect a DOT to Terminate IToken dot = context.Tokens.Dequeue(); if (dot.TokenType != Token.DOT) { throw ParserHelper.Error("Unexpected Token '" + dot.GetType().ToString() + "' encountered, expected a Dot (Line Terminator) Token to terminate a Prefix Directive", dot); } } catch (UriFormatException) { throw ParserHelper.Error("The URI '" + uri.Value + "' given for the prefix '" + prefix.Value + "' is not a valid Absolute URI", uri); } } else { throw ParserHelper.Error("Unexpected Token '" + prefix.GetType().ToString() + "' encountered, expected a URI Token after a Prefix Token", uri); } } else { throw ParserHelper.Error("Unexpected Token '" + prefix.GetType().ToString() + "' encountered, expected a Prefix Token after a Prefix Directive Token", prefix); } } else { throw ParserHelper.Error("Unexpected Token '" + directive.GetType().ToString() + "' encountered, expected a Base/Prefix Directive Token", directive); } }
private void TryParseTriple(TokenisingParserContext context) { // Get the Subject, Predicate and Object INode subj = TryParseSubject(context); INode pred = TryParsePredicate(context); INode obj = TryParseObject(context); // Ensure we're terminated by a DOT TryParseLineTerminator(context); // Assert the Triple if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) { ParserHelper.Stop(); } }
/// <summary> /// Parser method which parses a Binding Object which occurs in the array of Bindings /// </summary> private void ParseBinding(SparqlJsonParserContext context, bool headSeen) { //Can we read some properties if (context.Input.Read()) { SparqlResult result = new SparqlResult(); while (context.Input.TokenType != JsonToken.EndObject) { if (context.Input.TokenType == JsonToken.PropertyName) { //Each Property Name should be for a variable this.ParseBoundVariable(context, context.Input.Value.ToString(), result, headSeen); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected a Property Name giving the Binding for a Variable for this Result"); } //Get Next Token if (!context.Input.Read()) { throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object"); } } //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!result.HasValue(v)) { result.SetValue(v, null); } } //Add to Results result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } } else { throw new RdfParseException("Unexpected End of Input while trying to parse a Binding Object"); } }
/// <summary> /// Parser method which parses the 'vars' property of the Header Object /// </summary> private void ParseVariables(SparqlJsonParserContext context) { //Can we read the Variable Array if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartArray) { context.Input.Read(); while (context.Input.TokenType != JsonToken.EndArray) { if (context.Input.TokenType == JsonToken.String) { //Add to Variables if (!context.Handler.HandleVariable(context.Input.Value.ToString())) { ParserHelper.Stop(); } context.Variables.Add(context.Input.Value.ToString()); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a String giving the name of a Variable for the Result Set"); } context.Input.Read(); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected the Start of an Array giving the list of Variables for the 'vars' property of the Header Object of the JSON Result Set"); } } else { throw new RdfParseException("Unexpected End of Input while trying to parse the 'vars' property of the Header Object of the JSON Result Set"); } }
/// <summary> /// Parser method which parses Json Objects reprsenting Object Nodes /// </summary> /// <param name="context">Parser Context</param> /// <param name="subj">Subject of Triples which comes from the Great-Grandparent Json Object</param> /// <param name="pred">Predicate of Triples which comes form the Grandparent Json Object</param> private void ParseObject(JsonParserContext context, INode subj, INode pred) { String token, nodeValue, nodeType, nodeLang, nodeDatatype; nodeValue = nodeType = nodeLang = nodeDatatype = null; PositionInfo startPos = context.CurrentPosition; if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartObject) { context.Input.Read(); while (context.Input.TokenType != JsonToken.EndObject) { if (context.Input.TokenType == JsonToken.PropertyName) { token = context.Input.Value.ToString().ToLower(); //Check that we get a Property Value as a String context.Input.Read(); if (context.Input.TokenType != JsonToken.String) { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Value describing one of the properties of an Object Node", startPos); } //Extract the Information from the Object if (token.Equals("value")) { nodeValue = context.Input.Value.ToString(); } else if (token.Equals("type")) { nodeType = context.Input.Value.ToString().ToLower(); } else if (token.Equals("lang") || token.Equals("xml:lang")) { if (nodeLang == null && nodeDatatype == null) { nodeLang = context.Input.Value.ToString(); } else { throw Error(context, "Unexpected Language Property specified for an Object Node where a Language or Datatype has already been specified", startPos); } } else if (token.Equals("datatype")) { if (nodeDatatype == null && nodeLang == null) { nodeDatatype = context.Input.Value.ToString(); } else { throw Error(context, "Unexpected Datatype Property specified for an Object Node where a Language or Datatype has already been specified", startPos); } } else { throw Error(context, "Unexpected Property '" + token + "' specified for an Object Node, only 'value', 'type', 'lang' and 'datatype' are valid properties", startPos); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Name describing one of the properties of an Object Node", startPos); } context.Input.Read(); } //Validate the Information if (nodeType == null) { throw Error(context, "Cannot parse an Object Node from the JSON where no 'type' property was specified in the JSON Object representing the Node", startPos); } if (nodeValue == null) { throw Error(context, "Cannot parse an Object Node from the JSON where no 'value' property was specified in the JSON Object representing the Node", startPos); } //Turn this information into a Node INode obj; if (nodeType.Equals("uri")) { obj = context.Handler.CreateUriNode(new Uri(nodeValue)); } else if (nodeType.Equals("bnode")) { obj = context.Handler.CreateBlankNode(nodeValue.Substring(nodeValue.IndexOf(':') + 1)); } else if (nodeType.Equals("literal")) { if (nodeLang != null) { obj = context.Handler.CreateLiteralNode(nodeValue, nodeLang); } else if (nodeDatatype != null) { obj = context.Handler.CreateLiteralNode(nodeValue, new Uri(nodeDatatype)); } else { obj = context.Handler.CreateLiteralNode(nodeValue); } } else { throw Error(context, "Cannot parse an Object Node from the JSON where the 'type' property is not set to one of the permitted values 'uri', 'bnode' or 'literal' in the JSON Object representing the Node", startPos); } //Assert as a Triple if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) { ParserHelper.Stop(); } } } else { throw Error(context, "Unexpected End of Input while trying to parse an Object Node from the JSON", startPos); } }
/// <summary> /// Parser method which parses the 'vars' property of the Header Object /// </summary> private void ParseVariables(SparqlJsonParserContext context, bool bodySeen) { //Can we read the Variable Array if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartArray) { context.Input.Read(); List <String> vars = new List <string>(); while (context.Input.TokenType != JsonToken.EndArray) { if (context.Input.TokenType == JsonToken.String) { //Add to Variables if (!context.Handler.HandleVariable(context.Input.Value.ToString())) { ParserHelper.Stop(); } if (bodySeen) { // We've already seen the body in which case store locally for now vars.Add(context.Input.Value.ToString()); } else { // We're seeing the header first so just add to list of variables context.Variables.Add(context.Input.Value.ToString()); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType + "' with value '" + context.Input.Value + "' encountered, expected a String giving the name of a Variable for the Result Set"); } context.Input.Read(); } // If we've already seen the body check for variable conflicts if (!bodySeen) { return; } foreach (String var in context.Variables) { if (!vars.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a Binding Object binds a value to the variable '" + var + "' which is not defined in the Header Object in the value for the 'vars' property!"); } } foreach (String var in context.Variables) { if (!context.Handler.HandleVariable(var)) { ParserHelper.Stop(); } } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' with value '" + context.Input.Value + "' encountered, expected the Start of an Array giving the list of Variables for the 'vars' property of the Header Object of the JSON Result Set"); } } else { throw new RdfParseException("Unexpected End of Input while trying to parse the 'vars' property of the Header Object of the JSON Result Set"); } }
/// <summary> /// Parser method which parses Json Objects representing Triples /// </summary> /// <param name="context">Parser Context</param> private void ParseTriples(JsonParserContext context) { PositionInfo startPos = context.CurrentPosition; do { if (context.Input.TokenType == JsonToken.StartObject) { INode s, p, o; s = p = o = null; INode temp; TripleSegment segment; //Expect 3 Nodes in a Triple for (int i = 0; i < 3; i++) { temp = this.TryParseNode(context, out segment); switch (segment) { case TripleSegment.Object: if (o == null) { o = temp; } else { throw Error(context, "Duplicate object property encountered"); } break; case TripleSegment.Predicate: if (p == null) { p = temp; } else { throw Error(context, "Duplicate predicate property encountered"); } break; case TripleSegment.Subject: if (s == null) { s = temp; } else { throw Error(context, "Duplicate Subject property encountered"); } break; } } if (!context.Handler.HandleTriple((new Triple(s, p, o)))) { ParserHelper.Stop(); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, start of a JSON Object for a Triple was expected"); } //Then expect the end of the Object if (context.Input.Read()) { if (context.Input.TokenType != JsonToken.EndObject) { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + " encountered, expected the end of the JSON Object for a Triple"); } } else { throw Error(context, "Unexpected End of Input while trying to parse Triples from JSON, end of a Triple Object was expected", startPos); } //Then expect an End Array/Start Object if (!context.Input.Read()) { throw Error(context, "Unexpected End of Input while trying to parse Triples from JSON, end of JSON array or start of a JSON Object was expected", startPos); } } while (context.Input.TokenType == JsonToken.StartObject); }
private void TryParseResultRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); if (next.TokenType == Token.EOF) { context.Tokens.Dequeue(); return; } bool allowEOL = true, expectTab = false; int v = 0; SparqlResult result = new SparqlResult(); while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.URI: if (expectTab) { throw ParserHelper.Error("Unexpected URI, expected a Tab between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode uri = ParserHelper.TryResolveUri(context, next); result.SetValue(context.Variables[v], uri); v++; allowEOL = true; expectTab = true; break; case Token.BLANKNODEWITHID: if (expectTab) { throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2)); result.SetValue(context.Variables[v], blank); v++; allowEOL = true; expectTab = true; break; case Token.LITERAL: case Token.LONGLITERAL: case Token.PLAINLITERAL: if (expectTab) { throw ParserHelper.Error("Unexpected Blank Node, expected a Tab between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode lit = TryParseLiteral(context, next); result.SetValue(context.Variables[v], lit); v++; allowEOL = true; expectTab = true; break; case Token.EOL: if (allowEOL) { break; } else { if (v == context.Variables.Count - 1) { // If this is the last expected term then this must be an empty term v++; break; } throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next); } case Token.TAB: if (!expectTab) { // This is an empty field if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } v++; } expectTab = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) { throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } // Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) { break; } } if (v < context.Variables.Count) { throw ParserHelper.Error("Too few RDF Terms, got " + v + " but expected " + context.Variables.Count, next); } result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } }
private void TryParseTriple(XmlNode tripleEl, IRdfHandler handler, Uri graphUri) { //Verify Node Name if (!tripleEl.Name.Equals("triple")) { throw new RdfParseException("Unexpected Element <" + tripleEl.Name + "> encountered, only an optional <uri> element followed by zero/more <triple> elements are permitted within a <graph> element"); } //Verify number of Child Nodes if (!tripleEl.HasChildNodes) { throw new RdfParseException("<triple> element has no child nodes - 3 child nodes are expected"); } if (tripleEl.ChildNodes.Count < 3) { throw new RdfParseException("<triple> element has too few child nodes (" + tripleEl.ChildNodes.Count + ") - 3 child nodes are expected"); } if (tripleEl.ChildNodes.Count > 3) { throw new RdfParseException("<triple> element has too many child nodes (" + tripleEl.ChildNodes.Count + ") - 3 child nodes are expected"); } //Get the 3 Child Nodes XmlNode subjEl, predEl, objEl; subjEl = tripleEl.ChildNodes[0]; predEl = tripleEl.ChildNodes[1]; objEl = tripleEl.ChildNodes[2]; //Parse XML Nodes into RDF Nodes INode subj, pred, obj; if (subjEl.Name.Equals("uri")) { subj = handler.CreateUriNode(UriFactory.Create(subjEl.InnerText)); } else if (subjEl.Name.Equals("id")) { subj = handler.CreateBlankNode(subjEl.InnerText); } else { throw Error("Unexpected element <" + subjEl.Name + "> encountered, expected a <id>/<uri> element as the Subject of a Triple", subjEl); } if (predEl.Name.Equals("uri")) { pred = handler.CreateUriNode(UriFactory.Create(predEl.InnerText)); } else { throw Error("Unexpected element <" + predEl.Name + "> encountered, expected a <uri> element as the Predicate of a Triple", subjEl); } if (objEl.Name.Equals("uri")) { obj = handler.CreateUriNode(UriFactory.Create(objEl.InnerText)); } else if (objEl.Name.Equals("id")) { obj = handler.CreateBlankNode(objEl.InnerText); } else if (objEl.Name.Equals("plainLiteral")) { if (objEl.Attributes.GetNamedItem("xml:lang") != null) { obj = handler.CreateLiteralNode(objEl.InnerText, objEl.Attributes["xml:lang"].Value); } else { obj = handler.CreateLiteralNode(objEl.InnerText); } } else if (objEl.Name.Equals("typedLiteral")) { if (objEl.Attributes.GetNamedItem("datatype") != null) { Uri dtUri = UriFactory.Create(objEl.Attributes["datatype"].Value); if (objEl.FirstChild.NodeType == XmlNodeType.Text) { obj = handler.CreateLiteralNode(objEl.InnerText, dtUri); } else if (objEl.FirstChild.NodeType == XmlNodeType.CDATA) { obj = handler.CreateLiteralNode(objEl.FirstChild.InnerXml, dtUri); } else { obj = handler.CreateLiteralNode(objEl.InnerText, dtUri); } } else { throw Error("<typedLiteral> element does not have the required datatype attribute", objEl); } } else { throw Error("Unexpected element <" + objEl.Name + "> encountered, expected a <id>/<uri>/<plainLiteral>/<typedLiteral> element as the Object of a Triple", subjEl); } //Assert the resulting Triple if (!handler.HandleTriple(new Triple(subj, pred, obj, graphUri))) { ParserHelper.Stop(); } ; }
/// <summary> /// Internal Method which performs multi-threaded reading of data /// </summary> private void LoadGraphs(FolderStoreParserContext context) { //Create the relevant Parser IRdfReader parser; switch (context.Format) { case FolderStoreFormat.Turtle: parser = new TurtleParser(); break; case FolderStoreFormat.Notation3: parser = new Notation3Parser(); break; case FolderStoreFormat.RdfXml: parser = new RdfXmlParser(); break; default: parser = new TurtleParser(); break; } try { String file = context.GetNextFilename(); while (file != null) { //Read from Disk Graph g = new Graph(); String sourceFile = Path.Combine(context.Folder, file); parser.Load(g, sourceFile); //Add to Graph Collection foreach (Triple t in g.Triples) { if (context.Terminated) { break; } if (!context.Handler.HandleTriple(t)) { ParserHelper.Stop(); } } if (context.Terminated) { break; } //Get the Next Filename file = context.GetNextFilename(); } } catch (ThreadAbortException) { //We've been terminated, don't do anything #if !SILVERLIGHT Thread.ResetAbort(); #endif } catch (RdfParsingTerminatedException) { context.Terminated = true; context.ClearFilenames(); } catch (Exception ex) { throw new RdfStorageException("Error in Threaded Reader in Thread ID " + Thread.CurrentThread.ManagedThreadId, ex); } }
private void TryParseResultRow(TokenisingResultParserContext context) { IToken next = context.Tokens.Peek(); if (next.TokenType == Token.EOF) { context.Tokens.Dequeue(); return; } bool allowEOL = true, expectComma = false; int v = 0; SparqlResult result = new SparqlResult(); while (true) { next = context.Tokens.Dequeue(); switch (next.TokenType) { case Token.BLANKNODEWITHID: if (expectComma) { throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } INode blank = context.Handler.CreateBlankNode(next.Value.Substring(2)); result.SetValue(context.Variables[v], blank); v++; allowEOL = true; expectComma = true; break; case Token.LITERAL: case Token.PLAINLITERAL: if (expectComma) { throw ParserHelper.Error("Unexpected Blank Node, expected a comma between RDF Terms", next); } if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } // Try and guess what kind of term this is String lexicalForm = next.Value; INode value; if (lexicalForm.StartsWith("http://") || lexicalForm.StartsWith("https://") || lexicalForm.StartsWith("mailto:") || lexicalForm.StartsWith("ftp://")) { try { // Guessing a URI if starts with common URI prefix value = ParserHelper.TryResolveUri(context, next); } catch { // If invalid URI fall back to treating as literal value = context.Handler.CreateLiteralNode(lexicalForm); } } else { value = context.Handler.CreateLiteralNode(lexicalForm); } result.SetValue(context.Variables[v], value); v++; allowEOL = true; expectComma = true; break; case Token.EOL: if (allowEOL) { break; } else { if (v == context.Variables.Count - 1) { // If this is the last expected term then this must be an empty term v++; break; } throw ParserHelper.Error("Unexpected End of Line, expected a RDF Term Token", next); } case Token.COMMA: if (!expectComma) { // This is an empty field if (v >= context.Variables.Count) { throw ParserHelper.Error("Too many RDF Terms, only expecting " + context.Variables.Count + " terms", next); } v++; } expectComma = false; allowEOL = false; break; case Token.EOF: if (!allowEOL) { throw ParserHelper.Error("Unexpected EOF, expected another RDF Term for the Result Row", next); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } // Stop when we've hit the End of the Line/File if (next.TokenType == Token.EOL || next.TokenType == Token.EOF) { break; } } result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } }
private void TryParseObjectList(TriGParserContext context, Uri graphUri, INode subj, INode pred) { bool ok = false; do { //After the first run through we'll need to discard commas here if (ok) { context.Tokens.Dequeue(); } //Try to get the Object IToken obj = context.Tokens.Dequeue(); IToken next; INode objNode; switch (obj.TokenType) { case Token.COMMENT: //Discard and Continue ok = false; continue; case Token.QNAME: case Token.URI: objNode = ParserHelper.TryResolveUri(context, obj); break; case Token.LITERAL: case Token.LONGLITERAL: //Literals //See whether we get a Language Specifier/Data Type next next = context.Tokens.Peek(); if (next.TokenType == Token.LANGSPEC) { //Literal with Language Specifier context.Tokens.Dequeue(); objNode = context.Handler.CreateLiteralNode(obj.Value, next.Value); } else if (next.TokenType == Token.HATHAT) { //Literal with DataType context.Tokens.Dequeue(); //Now expect a QName/Uri Token next = context.Tokens.Dequeue(); if (next.TokenType == Token.QNAME || next.TokenType == Token.URI) { Uri dt = UriFactory.Create(Tools.ResolveUriOrQName(next, context.Namespaces, context.BaseUri)); objNode = context.Handler.CreateLiteralNode(obj.Value, dt); } else { throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a URI/QName Token to specify a Data Type after a ^^ Token", next); } } else { //Just a string literal objNode = context.Handler.CreateLiteralNode(obj.Value); } break; case Token.PLAINLITERAL: //Plain Literals Uri plt = TurtleSpecsHelper.InferPlainLiteralType((PlainLiteralToken)obj, TurtleSyntax.Original); objNode = context.Handler.CreateLiteralNode(obj.Value, plt); break; case Token.BLANKNODEWITHID: //Blank Node with ID objNode = context.Handler.CreateBlankNode(obj.Value.Substring(2)); break; case Token.LEFTSQBRACKET: //Blank Node next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTSQBRACKET) { //Anonymous Blank Node context.Tokens.Dequeue(); objNode = context.Handler.CreateBlankNode(); } else { //Blank Node Collection objNode = context.Handler.CreateBlankNode(); //Do an extra call to TryParsePredicateObjectList to parse the Blank Node Collection this.TryParsePredicateObjectList(context, graphUri, objNode); } break; case Token.RIGHTSQBRACKET: //End of Blank Node Collection if (!ok) { throw ParserHelper.Error("Unexpected Token '" + obj.GetType().ToString() + "' encountered before an Object list of a Blank Node Collection was parsed", obj); } return; case Token.LEFTBRACKET: //Collection //Check whether an Empty Collection next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTBRACKET) { //Empty Collection context.Tokens.Dequeue(); objNode = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil)); } else { //Collection objNode = context.Handler.CreateBlankNode(); this.TryParseCollection(context, graphUri, objNode); } break; case Token.EOF: throw ParserHelper.Error("Unexpected End of File while trying to parse Object List", obj); case Token.DOT: case Token.RIGHTCURLYBRACKET: case Token.SEMICOLON: if (!ok) { throw ParserHelper.Error("Unexpected Token '" + obj.GetType().ToString() + "' encountered before an Object list was parsed", obj); } return; default: //Unexpected Token throw ParserHelper.Error("Unexpected Token '" + obj.GetType().ToString() + "' encountered, expected a URI/QName/Blank Node as the Object of a Triple", obj); } ok = true; if (!context.Handler.HandleTriple(new Triple(subj, pred, objNode, graphUri))) { ParserHelper.Stop(); } } while (context.Tokens.Peek().TokenType == Token.COMMA); //Expect a comma if we are to continue }
private void TryParseCollection(TriGParserContext context, Uri graphUri, INode subj) { //Create the Nodes we need IUriNode rdfFirst, rdfRest, rdfNil; rdfFirst = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListFirst)); rdfRest = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListRest)); rdfNil = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil)); IToken next; INode item, temp; item = null; do { next = context.Tokens.Dequeue(); //Create a Node for this Token switch (next.TokenType) { case Token.COMMENT: //Discard and continue; continue; case Token.QNAME: case Token.URI: item = ParserHelper.TryResolveUri(context, next); break; case Token.LITERAL: case Token.LONGLITERAL: break; case Token.PLAINLITERAL: Uri plt = TurtleSpecsHelper.InferPlainLiteralType((PlainLiteralToken)next, TurtleSyntax.Original); item = context.Handler.CreateLiteralNode(next.Value, plt); break; case Token.LEFTSQBRACKET: //Check whether an anonymous Blank Node or a Blank Node Collection item = context.Handler.CreateBlankNode(); next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTSQBRACKET) { //Anonymous Blank Node context.Tokens.Dequeue(); } else { //Blank Node Collection this.TryParsePredicateObjectList(context, graphUri, item); } break; case Token.LEFTBRACKET: //Check whether an Empty Collection next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTBRACKET) { //Empty Collection context.Tokens.Dequeue(); item = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil)); } else { //Collection item = context.Handler.CreateBlankNode(); this.TryParseCollection(context, graphUri, item); } break; case Token.EOF: throw ParserHelper.Error("Unexpected End of File while trying to parse a Collection", next); default: //Unexpected Token throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, expected a URI/QName/Literal/Blank Node as an item in a Collection", next); } //Create the subj rdf:first item Triple if (!context.Handler.HandleTriple((new Triple(subj, rdfFirst, item, graphUri)))) { ParserHelper.Stop(); } //Create the rdf:rest Triple if (context.Tokens.Peek().TokenType == Token.RIGHTBRACKET) { //End of Collection context.Tokens.Dequeue(); if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, rdfNil, graphUri))) { ParserHelper.Stop(); } return; } else { //Continuing Collection temp = context.Handler.CreateBlankNode(); if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, temp, graphUri))) { ParserHelper.Stop(); } subj = temp; } } while (true); }
/// <summary> /// Tries to parse Base/Prefix declarations /// </summary> /// <param name="context">Parse Context</param> private void TryParseDirective(TokenisingParserContext context) { if (context.TraceParsing) { Console.WriteLine("Attempting to parse a Base/Prefix Declaration"); } //If we've been called an AT token has been encountered which we can discard context.Tokens.Dequeue(); //Then we expect either a Base Directive/Prefix Directive IToken directive = context.Tokens.Dequeue(); if (directive.TokenType == Token.BASEDIRECTIVE) { //Then expect a Uri for the Base Uri IToken u = context.Tokens.Dequeue(); if (u.TokenType == Token.URI) { //Set the Base Uri resolving against the current Base if any try { Uri baseUri = new Uri(Tools.ResolveUri(u.Value, context.BaseUri.ToSafeString())); context.BaseUri = baseUri; if (!context.Handler.HandleBaseUri(baseUri)) { ParserHelper.Stop(); } } catch (RdfException rdfEx) { throw new RdfParseException("Unable to set the Base URI to '" + u.Value + "' due to the following error:\n" + rdfEx.Message, u, rdfEx); } } else { throw ParserHelper.Error("Unexpected Token '" + u.GetType().ToString() + "' encountered, expected a URI after a Base Directive", u); } } else if (directive.TokenType == Token.PREFIXDIRECTIVE) { //Expect a Prefix then a Uri IToken pre = context.Tokens.Dequeue(); if (pre.TokenType == Token.PREFIX) { IToken ns = context.Tokens.Dequeue(); if (ns.TokenType == Token.URI) { //Register a Namespace resolving the Namespace Uri against the Base Uri try { Uri nsUri = new Uri(Tools.ResolveUri(ns.Value, context.BaseUri.ToSafeString())); String nsPrefix = (pre.Value.Length > 1) ? pre.Value.Substring(0, pre.Value.Length - 1) : String.Empty; context.Namespaces.AddNamespace(nsPrefix, nsUri); if (!context.Handler.HandleNamespace(nsPrefix, nsUri)) { ParserHelper.Stop(); } } catch (RdfException rdfEx) { throw new RdfParseException("Unable to resolve the Namespace URI '" + ns.Value + "' due to the following error:\n" + rdfEx.Message, ns, rdfEx); } } else { throw ParserHelper.Error("Unexpected Token '" + ns.GetType().ToString() + "' encountered, expected a URI after a Prefix Directive", pre); } } else { throw ParserHelper.Error("Unexpected Token '" + pre.GetType().ToString() + "' encountered, expected a Prefix after a Prefix Directive", pre); } } else { throw ParserHelper.Error("Unexpected Token '" + directive.GetType().ToString() + "' encountered, expected a Base/Prefix Directive after an @ symbol", directive); } //All declarations are terminated with a Dot IToken terminator = context.Tokens.Dequeue(); if (terminator.TokenType != Token.DOT) { throw ParserHelper.Error("Unexpected Token '" + terminator.GetType().ToString() + "' encountered, expected a Dot Line Terminator to terminate a Prefix/Base Directive", terminator); } }
/// <summary> /// Tries to parse directives /// </summary> /// <param name="context"></param> /// <param name="directive"></param> /// <remarks> /// This overload is needed because in some cases we may dequeue a token before we know it is a directive /// </remarks> private void TryParseDirective(TriGParserContext context, IToken directive) { //See what type of directive it is if (directive.TokenType == Token.BASEDIRECTIVE) { IToken baseUri = context.Tokens.Dequeue(); if (baseUri.TokenType == Token.URI) { try { Uri newBase = new Uri(Tools.ResolveUri(baseUri.Value, context.BaseUri.ToSafeString())); context.BaseUri = newBase; this.RaiseWarning("The @base directive is not valid in all versions of the TriG specification, your data may not be compatible with some older tools which do not support this version of TriG"); if (!context.Handler.HandleBaseUri(newBase)) { ParserHelper.Stop(); } } catch (UriFormatException) { throw ParserHelper.Error("The URI '" + baseUri.Value + "' given for the Base URI is not a valid URI", baseUri); } } else { throw ParserHelper.Error("Unexpected Token '" + baseUri.GetType().ToString() + "' encountered, expected a URI Token after a @base directive", baseUri); } } else if (directive.TokenType == Token.PREFIXDIRECTIVE) { //Prefix Directive IToken prefix = context.Tokens.Dequeue(); if (prefix.TokenType == Token.PREFIX) { IToken uri = context.Tokens.Dequeue(); if (uri.TokenType == Token.URI) { //Ensure the Uri is absolute try { Uri u = new Uri(Tools.ResolveUri(uri.Value, context.BaseUri.ToSafeString())); String pre = (prefix.Value.Equals(":")) ? String.Empty : prefix.Value.Substring(0, prefix.Value.Length - 1); context.Namespaces.AddNamespace(pre, u); if (!context.Handler.HandleNamespace(pre, u)) { ParserHelper.Stop(); } } catch (UriFormatException) { throw ParserHelper.Error("The URI '" + uri.Value + "' given for the prefix '" + prefix.Value + "' is not a valid URI", uri); } } else { throw ParserHelper.Error("Unexpected Token '" + prefix.GetType().ToString() + "' encountered, expected a URI Token after a Prefix Token", uri); } } else { throw ParserHelper.Error("Unexpected Token '" + prefix.GetType().ToString() + "' encountered, expected a Prefix Token after a Prefix Directive Token", prefix); } } else { throw ParserHelper.Error("Unexpected Token '" + directive.GetType().ToString() + "' encountered, expected a Base/Prefix Directive Token", directive); } //Expect a DOT to Terminate IToken dot = context.Tokens.Dequeue(); if (dot.TokenType != Token.DOT) { throw ParserHelper.Error("Unexpected Token '" + dot.GetType().ToString() + "' encountered, expected a Dot (Line Terminator) Token to terminate a Base/Prefix Directive", dot); } }
/// <summary> /// Tries to parse Collections. /// </summary> /// <param name="context">Parser Context.</param> /// <param name="firstSubj">Blank Node which is the head of the collection.</param> private void TryParseCollection(TurtleParserContext context, INode firstSubj) { // The opening bracket of the collection will already have been discarded when we get called IToken next; INode subj = firstSubj; INode obj = null, nextSubj; INode rdfFirst = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListFirst)); INode rdfRest = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListRest)); INode rdfNil = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil)); do { next = context.Tokens.Dequeue(); if (context.TraceParsing) { Console.WriteLine("Trying to parse a Collection item from Token '" + next.GetType().ToString() + "'"); } switch (next.TokenType) { case Token.BLANKNODE: obj = context.Handler.CreateBlankNode(); break; case Token.BLANKNODEWITHID: obj = context.Handler.CreateBlankNode(next.Value.Substring(2)); break; case Token.COMMENT: // Discard and continue continue; case Token.LEFTBRACKET: // Start of a collection so create a new Blank Node to be it's first subject next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTBRACKET) { // Empty Collection => rdf:nil context.Tokens.Dequeue(); obj = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil)); } else { obj = context.Handler.CreateBlankNode(); TryParseCollection(context, obj); } break; case Token.LEFTSQBRACKET: // Allowed Blank Node Collections as part of a Collection IToken temp = context.Tokens.Peek(); if (temp.TokenType == Token.RIGHTSQBRACKET) { // Anonymous Blank Node context.Tokens.Dequeue(); obj = context.Handler.CreateBlankNode(); } else { // Blank Node Collection obj = context.Handler.CreateBlankNode(); TryParsePredicateObjectList(context, obj, true); } break; case Token.LITERAL: case Token.LITERALWITHDT: case Token.LITERALWITHLANG: case Token.LONGLITERAL: case Token.PLAINLITERAL: obj = TryParseLiteral(context, next); break; case Token.QNAME: case Token.URI: obj = ParserHelper.TryResolveUri(context, next, false, context.QNameUnescapeFunction); break; case Token.RIGHTBRACKET: // We might terminate here if someone put a comment before the end of the Collection if (!context.Handler.HandleTriple(new Triple(subj, rdfFirst, obj))) { ParserHelper.Stop(); } if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, rdfNil))) { ParserHelper.Stop(); } return; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered while trying to parse a Collection", next); } // Assert the relevant Triples if (!context.Handler.HandleTriple(new Triple(subj, rdfFirst, obj))) { ParserHelper.Stop(); } if (context.Tokens.Peek().TokenType == Token.RIGHTBRACKET) { // End of the Collection context.Tokens.Dequeue(); if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, rdfNil))) { ParserHelper.Stop(); } return; } else { // More stuff in the collection nextSubj = context.Handler.CreateBlankNode(); if (!context.Handler.HandleTriple(new Triple(subj, rdfRest, nextSubj))) { ParserHelper.Stop(); } subj = nextSubj; } } while (true); }
/// <summary> /// Tries to parse Object lists. /// </summary> /// <param name="context">Parse Context.</param> /// <param name="subj">Subject of the Triples.</param> /// <param name="pred">Predicate of the Triples.</param> /// <param name="bnodeList">Whether this is a Blank Node Object list.</param> private void TryParseObjectList(TurtleParserContext context, INode subj, INode pred, bool bnodeList) { IToken objToken, next; INode obj = null; do { objToken = context.Tokens.Dequeue(); if (context.TraceParsing) { Console.WriteLine("Attempting to parse an Object List from the Object Token '" + objToken.GetType().ToString() + "'"); } switch (objToken.TokenType) { case Token.BLANKNODE: obj = context.Handler.CreateBlankNode(); break; case Token.BLANKNODEWITHID: obj = context.Handler.CreateBlankNode(objToken.Value.Substring(2)); break; case Token.COMMA: // Discard and continue - set object to null so we know we're expected to complete a triple if (obj != null) { obj = null; continue; } else { throw ParserHelper.Error("Unexpected Comma Triple terminator encountered, expected a valid Object for the current Triple", objToken); } case Token.COMMENT: // Discard and ignore continue; case Token.DOT: if (obj != null) { // OK to return if we've seen a valid Triple return; } else { throw ParserHelper.Error("Unexpected Dot Triple terminator encountered, expected a valid Object for the current Triple", objToken); } case Token.LEFTBRACKET: // Start of a collection so create a new Blank Node to be it's first subject next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTBRACKET) { // Empty Collection => rdf:nil context.Tokens.Dequeue(); obj = context.Handler.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfListNil)); } else { obj = context.Handler.CreateBlankNode(); TryParseCollection(context, obj); } break; case Token.LEFTSQBRACKET: // Start of a Blank Node collection? next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTSQBRACKET) { // An anonymous Blank Node context.Tokens.Dequeue(); obj = context.Handler.CreateBlankNode(); } else { // Start of a Blank Node Collection obj = context.Handler.CreateBlankNode(); TryParsePredicateObjectList(context, obj, true); } break; case Token.LITERAL: case Token.LITERALWITHDT: case Token.LITERALWITHLANG: case Token.LONGLITERAL: case Token.PLAINLITERAL: obj = TryParseLiteral(context, objToken); break; case Token.RIGHTSQBRACKET: if (bnodeList) { if (obj != null) { // Ok to return if we've seen a Triple return; } else { throw ParserHelper.Error("Unexpected Right Square Bracket encountered, expecting a valid object for the current Blank Node Predicate Object list", objToken); } } else { throw ParserHelper.Error("Unexpected Right Square Bracket encountered but not expecting the end of a Blank Node Predicate Object list", objToken); } case Token.SEMICOLON: if (obj != null) { // Ok to return if we've seen a Triple return; } else { throw ParserHelper.Error("Unexpected Semicolon Triple terminator encountered, expected a valid Object for the current Triple", objToken); } case Token.QNAME: case Token.URI: obj = ParserHelper.TryResolveUri(context, objToken, false, context.QNameUnescapeFunction); break; case Token.EOF: throw ParserHelper.Error("Unexpected end of file while trying to parse an Object list", objToken); default: throw ParserHelper.Error("Unexpected Token '" + objToken.GetType().ToString() + "' encountered while trying to parse an Object list", objToken); } // Assert the Triple if (!context.Handler.HandleTriple(new Triple(subj, pred, obj))) { ParserHelper.Stop(); } // Expect a comma/semicolon/dot terminator if we are to continue next = context.Tokens.Peek(); if (bnodeList) { // If in a Blank Node list a dot is not permitted but a ] is if (next.TokenType != Token.COMMA && next.TokenType != Token.SEMICOLON && next.TokenType != Token.RIGHTSQBRACKET) { throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered while trying to parse a Blank Node Object List, expected a comma, semicolon or ] to terminate the current Triple/list", next); } } else if (next.TokenType != Token.COMMA && next.TokenType != Token.SEMICOLON && next.TokenType != Token.DOT) { throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered while trying to parse an Object list, expected a comma, semicolon or dot to terminate the current Triple", next); } } while (true); }
/// <summary> /// Tries to parse Base/Prefix declarations. /// </summary> /// <param name="context">Parse Context.</param> /// <param name="turtleStyle">Whether declarations are Turtle style (if false SPARQL style is assumed).</param> private void TryParseDirective(TurtleParserContext context, bool turtleStyle) { if (context.TraceParsing) { Console.WriteLine("Attempting to parse a Base/Prefix Declaration"); } if (!turtleStyle && context.Syntax == TurtleSyntax.Original) { throw ParserHelper.Error("SPARQL style BASE/PREFIX declarations are not permitted in this Turtle syntax", context.Tokens.Dequeue()); } // If we've been called with turtleStyle set then an AT token has been encountered which we can discard if (turtleStyle) { context.Tokens.Dequeue(); } // Then we expect either a Base Directive/Prefix Directive IToken directive = context.Tokens.Dequeue(); if (directive.TokenType == Token.BASEDIRECTIVE) { // Then expect a Uri for the Base Uri IToken u = context.Tokens.Dequeue(); if (u.TokenType == Token.URI) { // Set the Base Uri resolving against the current Base if any try { Uri baseUri = UriFactory.Create(Tools.ResolveUri(u.Value, context.BaseUri.ToSafeString())); context.BaseUri = baseUri; if (!context.Handler.HandleBaseUri(baseUri)) { ParserHelper.Stop(); } } catch (RdfException rdfEx) { throw new RdfParseException("Unable to set the Base URI to '" + u.Value + "' due to the following error:\n" + rdfEx.Message, u, rdfEx); } } else { throw ParserHelper.Error("Unexpected Token '" + u.GetType().ToString() + "' encountered, expected a URI after a Base Directive", u); } } else if (directive.TokenType == Token.PREFIXDIRECTIVE) { // Expect a Prefix then a Uri IToken pre = context.Tokens.Dequeue(); if (pre.TokenType == Token.PREFIX) { IToken ns = context.Tokens.Dequeue(); if (ns.TokenType == Token.URI) { // Register a Namespace resolving the Namespace Uri against the Base Uri try { Uri nsUri = UriFactory.Create(Tools.ResolveUri(ns.Value, context.BaseUri.ToSafeString())); String nsPrefix = (pre.Value.Length > 1) ? pre.Value.Substring(0, pre.Value.Length - 1) : String.Empty; context.Namespaces.AddNamespace(nsPrefix, nsUri); if (!context.Handler.HandleNamespace(nsPrefix, nsUri)) { ParserHelper.Stop(); } } catch (RdfException rdfEx) { throw new RdfParseException("Unable to resolve the Namespace URI '" + ns.Value + "' due to the following error:\n" + rdfEx.Message, ns, rdfEx); } } else { throw ParserHelper.Error("Unexpected Token '" + ns.GetType().ToString() + "' encountered, expected a URI after a Prefix Directive", pre); } } else { throw ParserHelper.Error("Unexpected Token '" + pre.GetType().ToString() + "' encountered, expected a Prefix after a Prefix Directive", pre); } } else { throw ParserHelper.Error("Unexpected Token '" + directive.GetType().ToString() + "' encountered, expected a Base/Prefix Directive after an @ symbol", directive); } // Turtle sytle declarations are terminated with a Dot IToken terminator = context.Tokens.Peek(); if (terminator.TokenType != Token.DOT) { // If Turtle style the terminating . is required if (turtleStyle) { throw ParserHelper.Error("Unexpected Token '" + terminator.GetType().ToString() + "' encountered, expected a . to terminate a Base/Prefix Directive", terminator); } } else if (turtleStyle) { // Discard the . terminator for Turtle sytle declarations context.Tokens.Dequeue(); } else { // For SPARQL style the . terminator is forbidden throw ParserHelper.Error("Unexpected Token '" + terminator.GetType().ToString() + "' encountered, a . is not permitted/required to terminate a SPARQL style Base/Prefix Directive", terminator); } }
/// <summary> /// Internal method which actually parses the Result Set by traversing the RDF Graph appropriately /// </summary> /// <param name="context">Parser Context</param> private void Parse(SparqlRdfParserContext context) { try { context.Handler.StartResults(); //Create relevant Nodes context.Graph.NamespaceMap.AddNamespace("rdf", UriFactory.Create(NamespaceMapper.RDF)); context.Graph.NamespaceMap.AddNamespace("rs", UriFactory.Create(SparqlSpecsHelper.SparqlRdfResultsNamespace)); IUriNode rdfType = context.Graph.CreateUriNode("rdf:type"); IUriNode resultSetClass = context.Graph.CreateUriNode("rs:ResultSet"); IUriNode resultVariable = context.Graph.CreateUriNode("rs:resultVariable"); IUriNode solution = context.Graph.CreateUriNode("rs:solution"); IUriNode binding = context.Graph.CreateUriNode("rs:binding"); IUriNode value = context.Graph.CreateUriNode("rs:value"); IUriNode variable = context.Graph.CreateUriNode("rs:variable"); IUriNode boolean = context.Graph.CreateUriNode("rs:boolean"); //Try to get a ResultSet object Triple rset = context.Graph.Triples.WithPredicateObject(rdfType, resultSetClass).FirstOrDefault(); if (rset != null) { INode rsetID = rset.Subject; //Find the Variables the Result Set contains or the Boolean Value List <Triple> temp = context.Graph.Triples.WithSubjectPredicate(rsetID, boolean).ToList(); if (temp.Count > 0) { if (temp.Count > 1) { throw new RdfParseException("Result Set has more than one boolean result defined for it"); } Triple booleanResult = temp.First(); INode result = booleanResult.Object; if (result.NodeType == NodeType.Literal) { ILiteralNode lit = (ILiteralNode)result; if (lit.DataType != null) { if (lit.DataType.AbsoluteUri.Equals(XmlSpecsHelper.XmlSchemaDataTypeBoolean)) { bool b; if (Boolean.TryParse(lit.Value, out b)) { context.Handler.HandleBooleanResult(b); return; } else { throw new RdfParseException("Result Set has a boolean result which is a Literal typed as boolean but which does not contain a valid boolean value"); } } else { throw new RdfParseException("Result Set has a boolean result which is a Literal which is not boolean typed"); } } else { throw new RdfParseException("Result Set has a boolean result which is a Literal which is not typed as a boolean"); } } else { throw new RdfParseException("Result Set has a boolean result which is not a Literal Node"); } } else { //We're expected one/more variables temp = context.Graph.Triples.WithSubjectPredicate(rsetID, resultVariable).ToList(); if (temp.Count > 0) { foreach (Triple t in temp) { if (t.Object.NodeType == NodeType.Literal) { if (!context.Handler.HandleVariable(((ILiteralNode)t.Object).Value)) { ParserHelper.Stop(); } context.Variables.Add(((ILiteralNode)t.Object).Value); } else { throw new RdfParseException("Result Set has a result variable definition which is not a Literal Node"); } } } else { throw new RdfParseException("Result Set does not define any result variables or a boolean result"); } //Then we're expecting some Solutions temp = context.Graph.Triples.WithSubjectPredicate(rsetID, solution).ToList(); foreach (Triple slnTriple in temp) { //Each Solution has some Bindings INode slnID = slnTriple.Object; bool ok = false; SparqlResult r = new SparqlResult(); foreach (Triple bindingTriple in context.Graph.Triples.WithSubjectPredicate(slnID, binding)) { //Each Binding has a Variable and a Value ok = true; INode bindingID = bindingTriple.Object; String var = String.Empty; INode val = null; //Retrieve the Variable and the Bound Value foreach (Triple valueTriple in context.Graph.Triples.WithSubject(bindingID)) { if (valueTriple.Predicate.Equals(variable)) { if (!var.Equals(String.Empty)) { throw new RdfParseException("Result Set contains a Binding which refers to more than one Variable"); } if (valueTriple.Object.NodeType != NodeType.Literal) { throw new RdfParseException("Result Set contains a Binding which refers to a Variable but not by a Literal Node as required"); } var = ((ILiteralNode)valueTriple.Object).Value; } else if (valueTriple.Predicate.Equals(value)) { if (val != null) { throw new RdfParseException("Result Set contains a Binding which has more than one Value"); } val = valueTriple.Object; } } if (var.Equals(String.Empty) || val == null) { throw new RdfParseException("Result Set contains a Binding which doesn't contain both a Variable and a Value"); } //Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!"); } r.SetValue(var, val); } if (!ok) { throw new RdfParseException("Result Set contains a Solution which has no Bindings"); } //Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!r.HasValue(v)) { r.SetValue(v, null); } } if (!context.Handler.HandleResult(r)) { ParserHelper.Stop(); } } } } else { throw new RdfParseException("No Result Set object is defined in the Graph"); } context.Handler.EndResults(true); } catch (RdfParsingTerminatedException) { context.Handler.EndResults(true); } catch { context.Handler.EndResults(false); throw; } }
private void Parse(RdfACoreParserContext context) { try { context.Handler.StartRdf(); //Initialise Term Mappings context.HostLanguage.InitTermMappings(context); IRdfAEvent current; bool first = true; int nesting = 0; INode rdfType = context.Handler.CreateUriNode(new Uri(RdfSpecsHelper.RdfType)); List <IncompleteTriple> localIncompletes = new List <IncompleteTriple>(); do { localIncompletes.Clear(); //Dequeue the next event and increment/decrement nesting as appropriate current = context.Events.Dequeue(); switch (current.EventType) { case Event.Element: nesting++; context.IncrementNesting(); break; case Event.EndElement: context.DecrementNesting(); nesting--; continue; default: //Otherwise skip the event and continue continue; //throw new RdfParseException("Encountered an unexpected event of type '" + current.GetType().ToString() + "' when an Element/End Element event was expected", current.Position); } //Stop when nesting level returns to 0 if (nesting == 0) { break; } //Step 1 - Initialisation bool skip = false; INode newSubj = null, currObjResource = null, currObjLiteral = null; //Before carrying out further steps allow host specific special actions context.HostLanguage.ParseExtensions(context, current); //Step 2 - @profile parsing if (current.HasAttribute("profile")) { if (!this.ParseProfileAttribute(context, current)) { //If an @profile attribute fails to parse then must ignore the current subtree int i = 0; IRdfAEvent next; do { next = context.Events.Dequeue(); //Keep track of nesting in the subtree if (next.EventType == Event.Element) { i++; } if (next.EventType == Event.EndElement) { i--; } } while (i > 0 && next.EventType != Event.EndElement && context.Events.Count > 0); //If couldn't ignore a valid subtree then error if (context.Events.Count == 0) { throw new RdfParseException("Encountered an @profile attribute which pointed to a malformed profile which meant the relevant subtree of the document should be ignored but the document does not contain a well formed subtree"); } //If a bad @profile then continue after we've ignored the subtree continue; } } //Step 3 - @vocab parsing if (current.HasAttribute("vocab")) { this.ParseVocabAttribute(context, current); } //Step 4 - @prefix parsing (plus any other mechanisms defined by the host language) if (current.HasAttribute("prefix")) { this.ParsePrefixAttribute(context, current); } context.HostLanguage.ParsePrefixMappings(context, current); //Step 5 - Language parsing context.HostLanguage.ParseLiteralLanguage(context, current); if (!current.HasAttribute("rel") && !current.HasAttribute("rev")) { //Step 6 - If no @rel or @rev establish a subject newSubj = this.ParseSubject(context, current, nesting == 1, out skip); } else { //Step 7 - Use @rel or @rev to establish a subject and an object resource newSubj = this.ParseRelOrRevSubject(context, current, nesting == 1); currObjResource = this.ParseObjectResource(context, current); } //Step 8 - If there is a non-null subject process @typeof if (newSubj != null) { if (current.HasAttribute("typeof")) { foreach (INode n in this.ParseTypeofAttribute(context, current)) { if (!context.Handler.HandleTriple(new Triple(newSubj, rdfType, n))) { ParserHelper.Stop(); } } } } if (currObjResource != null) { //Step 9 - If there is a non-null object resource generate triples if (current.HasAttribute("rel")) { foreach (INode n in this.ParseRelAttribute(context, current)) { if (!context.Handler.HandleTriple(new Triple(newSubj, n, currObjResource))) { ParserHelper.Stop(); } } } if (current.HasAttribute("rev")) { foreach (INode n in this.ParseRevAttribute(context, current)) { if (!context.Handler.HandleTriple(new Triple(currObjResource, n, newSubj))) { ParserHelper.Stop(); } } } } else if (newSubj != null) { //Step 10 - If there is no object resource but there are predicates generate incomplete triples currObjResource = context.Handler.CreateBlankNode(); if (current.HasAttribute("rel")) { foreach (INode n in this.ParseRelAttribute(context, current)) { localIncompletes.Add(new IncompleteTriple(n, IncompleteTripleDirection.Forward)); } } if (current.HasAttribute("rev")) { foreach (INode n in this.ParseRevAttribute(context, current)) { localIncompletes.Add(new IncompleteTriple(n, IncompleteTripleDirection.Reverse)); } } } //Step 11 - Establish the current object literal if (newSubj != null && current.HasAttribute("property")) { //Must be an @property attribute in order for any triples to be generated List <INode> ps = this.ParsePropertyAttribute(context, current).ToList(); if (ps.Count > 0) { Uri dtUri; if (current.HasAttribute("content")) { //If @content is present then either a plain/typed literal if (current.HasAttribute("datatype")) { //@datatype is present so typed literal dtUri = this.ParseUri(context, current["datatype"], RdfACurieMode.TermOrCurieOrAbsUri); currObjLiteral = context.Handler.CreateLiteralNode(current["content"], dtUri); } else { //Plain literal currObjLiteral = context.Handler.CreateLiteralNode(current["content"], context.Language); } } else if (current.HasAttribute("datatype")) { //Typed literal dtUri = this.ParseUri(context, current["datatype"], RdfACurieMode.TermOrCurieOrAbsUri); if (dtUri != null) { if (dtUri.ToString().Equals(RdfSpecsHelper.RdfXmlLiteral)) { //XML Literal using element content currObjLiteral = context.Handler.CreateLiteralNode(this.ParseXmlContent(context), dtUri); } else { //Typed Literal using element content currObjLiteral = context.Handler.CreateLiteralNode(this.ParseTextContent(context), dtUri); } } else { //If datatype does not resolve fall back to plain literal using element content currObjLiteral = context.Handler.CreateLiteralNode(this.ParseTextContent(context), context.Language); } } else { //Plain Literal using element content currObjLiteral = context.Handler.CreateLiteralNode(this.ParseTextContent(context), context.Language); } //Generate the relevant triples foreach (INode p in ps) { if (!context.Handler.HandleTriple(new Triple(newSubj, p, currObjLiteral))) { ParserHelper.Stop(); } } } } //Step 12 - Complete any existing incomplete triples if (!skip && newSubj != null) { foreach (IncompleteTriple t in context.IncompleteTriples) { if (t.Direction == IncompleteTripleDirection.Forward) { if (!context.Handler.HandleTriple(new Triple(context.ParentSubject, t.Predicate, newSubj))) { ParserHelper.Stop(); } } else { if (!context.Handler.HandleTriple(new Triple(newSubj, t.Predicate, context.ParentSubject))) { ParserHelper.Stop(); } } } context.IncompleteTriples.Clear(); } //Step 13 - Set up for processing child elements if necessary //Can skip this if the next event is an end element if (context.Events.Peek().EventType != Event.EndElement) { context.ParentSubject = newSubj; if (currObjResource != null) { context.ParentObject = currObjResource; } else if (newSubj != null) { context.ParentObject = newSubj; } else { context.ParentObject = context.ParentSubject; } context.IncompleteTriples.AddRange(localIncompletes); } } while (context.Events.Count > 0); if (context.Events.Count > 0) { throw new RdfParseException("Source document is malformed! Encountered an end element which closes the document element but there are still more elements to be parsed", current.Position); } context.Handler.EndRdf(true); } catch (RdfParsingTerminatedException) { context.Handler.EndRdf(true); } catch { context.Handler.EndRdf(false); throw; } }
private void Parse(TriGParserContext context) { try { context.Handler.StartRdf(); //Expect a BOF Token IToken first = context.Tokens.Dequeue(); if (first.TokenType != Token.BOF) { throw ParserHelper.Error("Unexpected Token '" + first.GetType().ToString() + "' encountered, expected a BOF Token", first); } //Expect either a Directive or a Graph IToken next; do { next = context.Tokens.Peek(); switch (next.TokenType) { case Token.COMMENT: //Discard context.Tokens.Dequeue(); break; case Token.EOF: //End of File context.Tokens.Dequeue(); break; case Token.BASEDIRECTIVE: case Token.PREFIXDIRECTIVE: //Parse a Directive this.TryParseDirective(context); break; case Token.QNAME: case Token.URI: case Token.LEFTCURLYBRACKET: //Parse a Graph if (context.Syntax != TriGSyntax.Original) { //We must take care here because @prefix and @base directives may be Graph scoped so anything visible currently //remains visible and must be restored afterwards but anything inside the Graph is not visible outside of it Uri extBase = context.BaseUri; INamespaceMapper nsmap = new NamespaceMapper(context.Namespaces); this.TryParseGraph(context); //After we parse the Graph restore the state if (!context.Handler.HandleBaseUri(extBase)) { ParserHelper.Stop(); } context.BaseUri = extBase; context.Namespaces.Clear(); foreach (String prefix in nsmap.Prefixes) { if (!context.Handler.HandleNamespace(prefix, nsmap.GetNamespaceUri(prefix))) { ParserHelper.Stop(); } } context.Namespaces.Import(nsmap); } else { //With the old syntax declarations are file scoped so no need to worry about graph scoping this.TryParseGraph(context); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered", next); } } while (next.TokenType != Token.EOF); context.Handler.EndRdf(true); } catch (RdfParsingTerminatedException) { context.Handler.EndRdf(true); //Discard this - it justs means the Handler told us to stop } catch { context.Handler.EndRdf(false); throw; } }
/// <summary> /// Parses the XML Result Set format into a set of SPARQLResult objects /// </summary> /// <param name="context">Parser Context</param> private void Parse(SparqlXmlParserContext context) { try { context.Handler.StartResults(); // Get the Document Element and check it's a Sparql element if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input"); } while (context.Input.NodeType != XmlNodeType.Element) { if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as it was not possible to read a document element from the input"); } } if (!context.Input.Name.Equals("sparql")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set from the provided XML since the Document Element is not a <sparql> element!"); } // Go through it's attributes and check the Namespace is specified bool nsfound = false; if (context.Input.HasAttributes) { for (int i = 0; i < context.Input.AttributeCount; i++) { context.Input.MoveToNextAttribute(); if (context.Input.Name.Equals("xmlns")) { if (!context.Input.Value.Equals(SparqlSpecsHelper.SparqlNamespace)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element has an incorrect Namespace!"); } else { nsfound = true; } } } } if (!nsfound) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <sparql> element fails to specify the SPARQL Namespace!"); } // Get the Variables from the Header if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <head> element from the input"); } if (!context.Input.Name.Equals("head")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the first Child Node of the <sparql> element is not the required <head> element!"); } // Only parser <variable> and <link> elements if not an empty <head /> element if (!context.Input.IsEmptyElement) { while (context.Input.Read()) { // Stop reading when we hit the </head> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("head")) { break; } // Looking for <variable> elements if (context.Input.Name.Equals("variable")) { // Should only have 1 attribute if (context.Input.AttributeCount != 1) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <variable> element has too few/many attributes, only a 'name' attribute should be present!"); } else { // Add the Variable to the list context.Input.MoveToNextAttribute(); if (!context.Handler.HandleVariable(context.Input.Value)) { ParserHelper.Stop(); } context.Variables.Add(context.Input.Value); } } else if (context.Input.Name.Equals("link")) { // Not bothered about <link> elements } else { // Some unexpected element throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <head> contains an unexpected element <" + context.Input.Name + ">!"); } } } if (!context.Input.Name.Equals("head")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </head> element was found"); } // Look at the <results> or <boolean> element if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as could not read a <results> element from the input"); } if (context.Input.Name.Equals("results")) { // Only parser <result> elements if it's not an empty <results /> element if (!context.Input.IsEmptyElement) { while (context.Input.Read()) { // Stop reading when we hit the </results> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("results")) { break; } // Must be a <result> element if (!context.Input.Name.Equals("result")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <results> element contains an unexpected element <" + context.Input.Name + ">!"); } // Empty Elements generate an Empty Result if (context.Input.IsEmptyElement) { if (!context.Handler.HandleResult(new SparqlResult())) { ParserHelper.Stop(); } continue; } // Get the values of each Binding String var; INode value; SparqlResult result = new SparqlResult(); while (context.Input.Read()) { // Stop reading when we hit the </binding> if (context.Input.NodeType == XmlNodeType.EndElement && context.Input.Name.Equals("result")) { break; } // Must be a <binding> element if (!context.Input.Name.Equals("binding")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <result> element contains an unexpected element <" + context.Input.Name + ">!"); } // Must have only 1 attribute if (context.Input.AttributeCount != 1) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element has too few/many attributes, only a 'name' attribute should be present!"); } // Get the Variable this is a binding for and its Value context.Input.MoveToNextAttribute(); var = context.Input.Value; if (!context.Input.Read()) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of input when the contents of a <binding> element was expected"); } value = ParseValue(context); // Check that the Variable was defined in the Header if (!context.Variables.Contains(var)) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since a <binding> element attempts to bind a value to the variable '" + var + "' which is not defined in the <head> by a <variable> element!"); } // Set the Variable to the Value result.SetValue(var, value); } // Check that all Variables are bound for a given result binding nulls where appropriate foreach (String v in context.Variables) { if (!result.HasValue(v)) { result.SetValue(v, null); } } if (!context.Input.Name.Equals("result")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before a closing </result> element was found"); } // Add to results set result.SetVariableOrdering(context.Variables); if (!context.Handler.HandleResult(result)) { ParserHelper.Stop(); } } } if (!context.Input.Name.Equals("results")) { throw new RdfParseException("Unable to Parse a SPARQL Result Set as reached the end of the input before the closing </results> element was found"); } } else if (context.Input.Name.Equals("boolean")) { // Can't be any <variable> elements if (context.Variables.Count > 0) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element is specified but the <head> contained one/more <variable> elements which is not permitted!"); } try { // Get the value of the <boolean> element as a Boolean Boolean b = Boolean.Parse(context.Input.ReadInnerXml()); context.Handler.HandleBooleanResult(b); } catch (Exception) { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the <boolean> element contained a value that could not be understood as a Boolean value!"); } } else { throw new RdfParseException("Unable to Parse a SPARQL Result Set since the second Child Node of the <sparql> element is not the required <results> or <boolean> element!"); } context.Handler.EndResults(true); } catch (RdfParsingTerminatedException) { context.Handler.EndResults(true); } catch { // Some other Error context.Handler.EndResults(false); throw; } }