/// <summary> /// Converts the Algebra to a Graph Pattern /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern gp = this._inner.ToGraphPattern(); if (gp.HasModifier) { GraphPattern p = new GraphPattern(); p.AddGraphPattern(gp); p.AddAssignment(new BindPattern(this._var, this._expr)); return p; } else { gp.AddAssignment(new BindPattern(this._var, this._expr)); return gp; } }
/// <summary> /// Converts the Algebra into a Graph Pattern /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern p = new GraphPattern(this._pattern); if (!p.HasModifier) { p.IsService = true; p.GraphSpecifier = this._endpointSpecifier; return p; } else { GraphPattern parent = new GraphPattern(); parent.IsService = true; parent.GraphSpecifier = this._endpointSpecifier; parent.AddGraphPattern(p); return parent; } }
/// <summary> /// Converts the Algebra back to a SPARQL Query /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern p = new GraphPattern(); p.IsUnion = true; p.AddGraphPattern(this._lhs.ToGraphPattern()); p.AddGraphPattern(this._rhs.ToGraphPattern()); return p; }
private void TryParseMinusClause(SparqlQueryParserContext context, GraphPattern p) { if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_0) throw new RdfParseException("MINUS clauses are not supported in SPARQL 1.0"); //MINUS generates a new child graph pattern GraphPattern child = this.TryParseGraphPattern(context); child.IsMinus = true; p.AddGraphPattern(child); }
private void TryParseServiceClause(SparqlQueryParserContext context, GraphPattern p) { if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_0) throw new RdfParseException("SERVICE clauses are not supported in SPARQL 1.0"); //May allow an optional SILENT keyword bool silent = false; if (context.Tokens.Peek().TokenType == Token.SILENT) { context.Tokens.Dequeue(); silent = true; } //SERVICE first has a URI/Variable service specifier IToken specifier = context.Tokens.Dequeue(); if (specifier.TokenType != Token.URI && specifier.TokenType != Token.VARIABLE) { throw ParserHelper.Error("Unexpected Token '" + specifier.GetType().ToString() + "' encountered, expected a URI/Variable after a SERVICE keyword", specifier); } //Then a Graph Pattern GraphPattern child = this.TryParseGraphPattern(context); child.IsService = true; child.GraphSpecifier = specifier; child.IsSilent = silent; p.AddGraphPattern(child); }
private void TryParseUnionClause(SparqlQueryParserContext context, GraphPattern p) { //Create a new Pattern which will hold the UNION GraphPattern union = new GraphPattern(); union.IsUnion = true; //Add the Last Child Pattern of the Parent as that is the start of the UNION GraphPattern lastchild = p.LastChildPattern(); if (lastchild.IsSimplifiable) { union.AddGraphPattern(lastchild.LastChildPattern()); } else { union.AddGraphPattern(lastchild); } GraphPattern child = this.TryParseGraphPattern(context, true); union.AddGraphPattern(child); //Check for multiple IToken next = context.Tokens.Peek(); while (next.TokenType == Token.UNION) { context.Tokens.Dequeue(); union.AddGraphPattern(this.TryParseGraphPattern(context, true)); next = context.Tokens.Peek(); } p.AddGraphPattern(union); }
private void TryParseExistsClause(SparqlQueryParserContext context, GraphPattern p, bool exists) { if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_0) throw new RdfParseException("EXISTS and NOT EXISTS clauses are not supported in SPARQL 1.0"); if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_1) throw new RdfParseException("EXISTS and NOT EXISTS clauses can only be used inside FILTER clauses in SPARQL 1.1"); //EXISTS and NOT EXISTS generate a new Child Graph Pattern GraphPattern child = this.TryParseGraphPattern(context); if (exists) { child.IsExists = true; } else { child.IsNotExists = true; } p.AddGraphPattern(child); }
private void TryParseGraphClause(SparqlQueryParserContext context, GraphPattern p) { //Graph Clauses generate a child Graph Pattern //Get the Graph Specifier - must be a Variable/IRIRef IToken graphspec = context.Tokens.Dequeue(); if (graphspec.TokenType != Token.URI && graphspec.TokenType != Token.QNAME && graphspec.TokenType != Token.VARIABLE) { throw ParserHelper.Error("Unexpected Token '" + graphspec.GetType().ToString() + "' encountered, expected a URI/QName/Variable Token to specify the active Graph for a GRAPH Clause", graphspec); } //Convert a QName or Relative Uri to a Absolute Uri if (graphspec.TokenType != Token.VARIABLE) { String u = Tools.ResolveUriOrQName(graphspec, context.Query.NamespaceMap, context.Query.BaseUri); if (!u.Equals(graphspec.Value)) { graphspec = new UriToken("<" + u + ">", graphspec.StartLine, graphspec.StartPosition, graphspec.EndPosition); } } else { context.Query.AddVariable(graphspec.Value); } GraphPattern child = this.TryParseGraphPattern(context); child.IsGraph = true; child.GraphSpecifier = graphspec; p.AddGraphPattern(child); }
private void TryParseOptionalClause(SparqlQueryParserContext context, GraphPattern p) { //Optional Clauses generate a child Graph Pattern GraphPattern child = this.TryParseGraphPattern(context); child.IsOptional = true; p.AddGraphPattern(child); }
private void TryParseTriplePatterns(SparqlQueryParserContext context, GraphPattern p) { int lasttoken = context.Tokens.LastTokenType; IToken next = context.Tokens.Dequeue(); //Allowed a Variable/RDF Term/Collection //OR we might go straight to a OPTIONAL/GRAPH/UNION/FILTER/EXISTS/NOT EXISTS/LET switch (next.TokenType) { case Token.COMMENT: //Comments are discardable this.TryParseTriplePatterns(context, p); break; case Token.VARIABLE: //Variable context.LocalTokens.Push(next); context.Query.AddVariable(next.Value); this.TryParsePredicateObjectList(context, p,2); break; case Token.URI: case Token.QNAME: case Token.LITERAL: case Token.LONGLITERAL: case Token.PLAINLITERAL: //Must then be followed be a non-empty Property List context.LocalTokens.Push(next); this.TryParsePredicateObjectList(context, p,2); break; case Token.BLANKNODE: case Token.BLANKNODEWITHID: //Check list of Blank Node usages if (context.BlankNodeIDUsages.ContainsKey(next.Value)) { if (context.BlankNodeIDUsages[next.Value] != context.GraphPatternID) { throw ParserHelper.Error("Invalid use of Blank Node Label '" + next.Value + "', this Label has already been used in a different Graph Pattern", next); } } else { context.BlankNodeIDUsages.Add(next.Value, context.GraphPatternID); } //Must then be followed be a non-empty Property List context.LocalTokens.Push(next); this.TryParsePredicateObjectList(context, p, 2); break; case Token.LET: //LET assignment this.TryParseLetAssignment(context, p); break; case Token.BIND: //BIND assignment this.TryParseBindAssignment(context, p); break; case Token.LEFTSQBRACKET: //Start of Blank Node Collection //Create a new Blank Node Token BlankNodeWithIDToken bnode = new BlankNodeWithIDToken(context.GetNewBlankNodeID(), 0, 0, 0); //Push twice, once for Subject of Collection context.LocalTokens.Push(bnode); next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTSQBRACKET) { //Single anonymous blank node context.Tokens.Dequeue(); //Parse as Subject of Triples this.TryParsePredicateObjectList(context, p, 2); } else { //Parse the Collection this.TryParsePredicateObjectList(context, p, 2); //Push again for subject of Triples context.LocalTokens.Push(bnode); this.TryParsePredicateObjectList(context, p, 2); } break; case Token.LEFTBRACKET: //Collection this.TryParseCollection(context, p, false); this.TryParsePredicateObjectList(context, p, 2); break; case Token.FILTER: //FILTER Pattern this.TryParseFilterClause(context, p); break; case Token.OPTIONAL: //OPTIONAL Clause this.TryParseOptionalClause(context, p); break; case Token.EXISTS: case Token.NOTEXISTS: case Token.UNSAID: //EXISTS/NOT EXISTS clause if (next.TokenType == Token.UNSAID && context.SyntaxMode != SparqlQuerySyntax.Extended) throw new RdfParseException("The UNSAID Keyword is only supported when syntax is set to Extended. It is an alias for NOT EXISTS which can be used when the syntax is set to SPARQL 1.1/Extended"); this.TryParseExistsClause(context, p, (next.TokenType == Token.EXISTS)); break; case Token.MINUS_P: //MINUS clause this.TryParseMinusClause(context, p); break; case Token.SERVICE: //SERVICE clause this.TryParseServiceClause(context, p); break; case Token.SELECT: //Sub-query this.TryParseSubquery(context, p); break; case Token.GRAPH: //GRAPH Clause this.TryParseGraphClause(context, p); break; case Token.UNION: //UNION Clause this.TryParseUnionClause(context, p); break; case Token.LEFTCURLYBRACKET: //Nested Graph Pattern p.AddGraphPattern(this.TryParseGraphPattern(context, false)); //Simplify Subqueries if (p.ChildGraphPatterns.Last().IsSubQuery) { GraphPattern temp = p.LastChildPattern(); p.AddTriplePattern(temp.TriplePatterns.First()); } break; case Token.DOT: //Can Discard this if last character was the end of a nested Graph pattern if (lasttoken == Token.RIGHTCURLYBRACKET || lasttoken == Token.RIGHTBRACKET) { //Can Discard this if the next character is not another DOT next = context.Tokens.Peek(); if (next.TokenType != Token.DOT) { if (next.TokenType != Token.RIGHTCURLYBRACKET) { this.TryParseTriplePatterns(context, p); } else { return; } } else { throw ParserHelper.Error("A DOT Token cannot follow another DOT Token within a Graph Pattern", next); } } else if (lasttoken == Token.SEMICOLON) { //Allow Trailing Semicolon return; } else { throw ParserHelper.Error("A DOT Token can only be used to terminate a Triple Pattern or a Nested Graph Pattern", next); } break; default: throw ParserHelper.Error("Unexpected Token '" + next.GetType().ToString() + "' encountered when the start of a Triple Pattern was expected", next); } }
/// <summary> /// Tries to parse a Graph Pattern from the given Parser Context /// </summary> /// <param name="context">Parser Context</param> /// <param name="requireOpeningLeftBracket">Whether the opening Left Curly Bracket is required</param> /// <returns></returns> protected internal GraphPattern TryParseGraphPattern(SparqlQueryParserContext context, bool requireOpeningLeftBracket) { context.GraphPatternID++; IToken next; if (requireOpeningLeftBracket) { //Discard the opening { next = context.Tokens.Dequeue(); if (next.TokenType != Token.LEFTCURLYBRACKET) { throw ParserHelper.Error("Unexpected Token encountered, expected the start of a Graph Pattern", next); } } next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTCURLYBRACKET) { //Empty Graph Pattern - Selects nothing context.Tokens.Dequeue(); GraphPattern pattern = new GraphPattern(); return pattern; } else if (next.TokenType == Token.LEFTCURLYBRACKET) { //Nested Graph Pattern GraphPattern pattern = new GraphPattern(); GraphPattern child;// = new GraphPattern(); child = this.TryParseGraphPattern(context, true); //this.TryParseTriplePatterns(context, child); pattern.AddGraphPattern(child); child = new GraphPattern(); //Keep Parsing Graph Patterns until we hit a Right Curly Bracket do { next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTCURLYBRACKET) { //This isn't in the switch as we want to break out of the loop when we get here context.Tokens.Dequeue(); break; } else { switch (next.TokenType) { case Token.UNION: //UNION Clause if (!child.IsEmpty) { pattern.AddGraphPattern(child); child = new GraphPattern(); } context.Tokens.Dequeue(); this.TryParseUnionClause(context, pattern); break; case Token.FILTER: //FILTER Clause context.Tokens.Dequeue(); this.TryParseFilterClause(context, pattern); break; case Token.OPTIONAL: //OPTIONAL Clause if (!child.IsEmpty) { pattern.AddGraphPattern(child); child = new GraphPattern(); } context.Tokens.Dequeue(); this.TryParseOptionalClause(context, pattern); break; case Token.GRAPH: //GRAPH Clause if (!child.IsEmpty) { pattern.AddGraphPattern(child); child = new GraphPattern(); } context.Tokens.Dequeue(); this.TryParseGraphClause(context, pattern); break; case Token.EXISTS: case Token.NOTEXISTS: case Token.UNSAID: //EXISTS/NOT EXISTS/UNSAID Clause if (next.TokenType == Token.UNSAID && context.SyntaxMode != SparqlQuerySyntax.Extended) throw new RdfParseException("The UNSAID Keyword is only supported when syntax is set to Extended. It is an alias for NOT EXISTS which can be used when the syntax is set to SPARQL 1.1/Extended"); if (!child.IsEmpty) { pattern.AddGraphPattern(child); child = new GraphPattern(); } context.Tokens.Dequeue(); this.TryParseExistsClause(context, pattern, (next.TokenType == Token.EXISTS)); break; case Token.MINUS_P: //MINUS Clause if (!child.IsEmpty) { pattern.AddGraphPattern(child); child = new GraphPattern(); } context.Tokens.Dequeue(); this.TryParseMinusClause(context, pattern); break; case Token.SERVICE: //SERVICE clause if (!child.IsEmpty) { pattern.AddGraphPattern(child); child = new GraphPattern(); } context.Tokens.Dequeue(); this.TryParseServiceClause(context, pattern); break; case Token.VARIABLE: case Token.URI: case Token.QNAME: case Token.LITERAL: case Token.LONGLITERAL: case Token.PLAINLITERAL: case Token.BLANKNODE: case Token.BLANKNODEWITHID: case Token.LET: case Token.BIND: case Token.LEFTSQBRACKET: case Token.LEFTBRACKET: //Start of some Triple Patterns context.GraphPatternID++; this.TryParseTriplePatterns(context, child); break; default: //Otherwise we'll expect a new Graph Pattern pattern.AddGraphPattern(this.TryParseGraphPattern(context, true)); break; } } } while (true); if (!child.IsEmpty) { pattern.AddGraphPattern(child); } return pattern; } else { //Non-Empty Graph Pattern GraphPattern pattern = new GraphPattern(); this.TryParseTriplePatterns(context, pattern); //Keep parsing Triple Patterns until we hit a Right Curly Bracket do { next = context.Tokens.Peek(); if (next.TokenType == Token.RIGHTCURLYBRACKET) { break; } else { this.TryParseTriplePatterns(context, pattern); } } while (true); //Discard the Right Curly Bracket context.Tokens.Dequeue(); return pattern; } }
/// <summary> /// Converts the Minus() back to a MINUS Graph Pattern /// </summary> /// <returns></returns> public GraphPattern ToGraphPattern() { GraphPattern p = this._lhs.ToGraphPattern(); GraphPattern opt = this._rhs.ToGraphPattern(); if (!opt.HasModifier) { opt.IsMinus = true; p.AddGraphPattern(opt); } else { GraphPattern parent = new GraphPattern(); parent.AddGraphPattern(opt); parent.IsMinus = true; p.AddGraphPattern(parent); } return p; }