private ISparqlExpression TryParseBuiltInCall(Queue<IToken> tokens) { IToken next = tokens.Dequeue(); bool comma = false, first = true; List<ISparqlExpression> args; ISparqlExpression strExpr; switch (next.TokenType) { case Token.ABS: return new AbsFunction(this.TryParseBrackettedExpression(tokens)); case Token.BNODE: return new BNodeFunction(this.TryParseBrackettedExpression(tokens)); case Token.BOUND: //Expect a Left Bracket, Variable and then a Right Bracket next = tokens.Dequeue(); if (next.TokenType == Token.LEFTBRACKET) { next = tokens.Dequeue(); if (next.TokenType == Token.VARIABLE) { VariableExpressionTerm varExpr = new VariableExpressionTerm(next.Value); next = tokens.Dequeue(); if (next.TokenType == Token.RIGHTBRACKET) { return new BoundFunction(varExpr); } else { throw Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, a Right Bracket to end a BOUND function call was expected",next); } } else { throw Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, a Variable Token for a BOUND function call was expected", next); } } else { throw Error("Unexpected Token '" + next.GetType().ToString() + "' encountered, a Left Bracket to start a BOUND function call was expected", next); } case Token.CEIL: return new CeilFunction(this.TryParseBrackettedExpression(tokens)); case Token.COALESCE: //Get as many argument expressions as we can args = new List<ISparqlExpression>(); do { args.Add(this.TryParseBrackettedExpression(tokens, first, out comma)); first = false; } while (comma); return new CoalesceFunction(args); case Token.CONCAT: //Get as many argument expressions as we can args = new List<ISparqlExpression>(); do { args.Add(this.TryParseBrackettedExpression(tokens, first, out comma)); first = false; } while (comma); return new ConcatFunction(args); case Token.CONTAINS: return new ContainsFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.DATATYPEFUNC: return new DataTypeFunction(this.TryParseBrackettedExpression(tokens)); case Token.DAY: return new DayFunction(this.TryParseBrackettedExpression(tokens)); case Token.ENCODEFORURI: return new EncodeForUriFunction(this.TryParseBrackettedExpression(tokens)); case Token.FLOOR: return new FloorFunction(this.TryParseBrackettedExpression(tokens)); case Token.HOURS: return new HoursFunction(this.TryParseBrackettedExpression(tokens)); case Token.IF: return new IfElseFunction(this.TryParseBrackettedExpression(tokens, true, out comma), this.TryParseBrackettedExpression(tokens, false, out comma), this.TryParseBrackettedExpression(tokens, false, out comma)); case Token.IRI: case Token.URIFUNC: return new IriFunction(this.TryParseBrackettedExpression(tokens)); case Token.ISBLANK: return new IsBlankFunction(this.TryParseBrackettedExpression(tokens)); case Token.ISIRI: return new IsIriFunction(this.TryParseBrackettedExpression(tokens)); case Token.ISLITERAL: return new IsLiteralFunction(this.TryParseBrackettedExpression(tokens)); case Token.ISNUMERIC: return new IsNumericFunction(this.TryParseBrackettedExpression(tokens)); case Token.ISURI: return new IsUriFunction(this.TryParseBrackettedExpression(tokens)); case Token.LANG: return new LangFunction(this.TryParseBrackettedExpression(tokens)); case Token.LANGMATCHES: return new LangMatchesFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.LCASE: return new LCaseFunction(this.TryParseBrackettedExpression(tokens)); case Token.MD5: return new MD5HashFunction(this.TryParseBrackettedExpression(tokens)); case Token.MINUTES: return new MinutesFunction(this.TryParseBrackettedExpression(tokens)); case Token.MONTH: return new MonthFunction(this.TryParseBrackettedExpression(tokens)); case Token.NOW: //Expect a () after the Keyword Token next = tokens.Dequeue(); if (next.TokenType != Token.LEFTBRACKET) throw Error("Expected a Left Bracket after a NOW keyword to call the NOW() function", next); next = tokens.Dequeue(); if (next.TokenType != Token.RIGHTBRACKET) throw Error("Expected a Right Bracket after NOW( since the NOW() function does not take any arguments", next); return new NowFunction(); case Token.RAND: //Expect a () after the Keyword Token next = tokens.Dequeue(); if (next.TokenType != Token.LEFTBRACKET) throw Error("Expected a Left Bracket after a RAND keyword to call the RAND() function", next); next = tokens.Dequeue(); if (next.TokenType != Token.RIGHTBRACKET) throw Error("Expected a Right Bracket after RAND( since the RAND() function does not take any arguments", next); return new RandFunction(); case Token.REGEX: return this.TryParseRegexExpression(tokens); case Token.REPLACE: //REPLACE may have 3/4 arguments strExpr = this.TryParseBrackettedExpression(tokens); ISparqlExpression patternExpr = this.TryParseBrackettedExpression(tokens, false); ISparqlExpression replaceExpr = this.TryParseBrackettedExpression(tokens, false, out comma); if (comma) { ISparqlExpression opsExpr = this.TryParseBrackettedExpression(tokens, false); return new ReplaceFunction(strExpr, patternExpr, replaceExpr, opsExpr); } else { return new ReplaceFunction(strExpr, patternExpr, replaceExpr); } case Token.ROUND: return new RoundFunction(this.TryParseBrackettedExpression(tokens)); case Token.SAMETERM: return new SameTermFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.SECONDS: return new SecondsFunction(this.TryParseBrackettedExpression(tokens)); case Token.SHA1: return new Sha1HashFunction(this.TryParseBrackettedExpression(tokens)); case Token.SHA224: return new Sha224HashFunction(this.TryParseBrackettedExpression(tokens)); case Token.SHA256: return new Sha256HashFunction(this.TryParseBrackettedExpression(tokens)); case Token.SHA384: return new Sha384HashFunction(this.TryParseBrackettedExpression(tokens)); case Token.SHA512: return new Sha512HashFunction(this.TryParseBrackettedExpression(tokens)); case Token.STR: return new StrFunction(this.TryParseBrackettedExpression(tokens)); case Token.STRAFTER: return new StrAfterFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.STRBEFORE: return new StrBeforeFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.STRDT: return new StrDtFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.STRENDS: return new StrEndsFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.STRLANG: return new StrLangFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.STRLEN: return new StrLenFunction(this.TryParseBrackettedExpression(tokens)); case Token.STRSTARTS: return new StrStartsFunction(this.TryParseBrackettedExpression(tokens), this.TryParseBrackettedExpression(tokens, false)); case Token.SUBSTR: //SUBSTR may have 2/3 arguments strExpr = this.TryParseBrackettedExpression(tokens); ISparqlExpression startExpr = this.TryParseBrackettedExpression(tokens, false, out comma); if (comma) { ISparqlExpression lengthExpr = this.TryParseBrackettedExpression(tokens, false); return new SubStrFunction(strExpr, startExpr, lengthExpr); } else { return new SubStrFunction(strExpr, startExpr); } case Token.TIMEZONE: return new TimezoneFunction(this.TryParseBrackettedExpression(tokens)); case Token.TZ: return new TZFunction(this.TryParseBrackettedExpression(tokens)); case Token.UCASE: return new UCaseFunction(this.TryParseBrackettedExpression(tokens)); case Token.YEAR: return new YearFunction(this.TryParseBrackettedExpression(tokens)); case Token.EXISTS: case Token.NOTEXISTS: if (this._syntax == SparqlQuerySyntax.Sparql_1_0) throw new RdfParseException("EXISTS/NOT EXISTS clauses are not supported in SPARQL 1.0"); if (this._parser == null) throw new RdfParseException("Unable to parse an EXISTS/NOT EXISTS as there is no Query Parser to call into"); //Gather Tokens for the Pattern NonTokenisedTokenQueue temptokens = new NonTokenisedTokenQueue(); int openbrackets = 0; bool mustExist = (next.TokenType == Token.EXISTS); do { if (tokens.Count == 0) throw new RdfParseException("Unexpected end of Tokens while trying to parse an EXISTS/NOT EXISTS function"); next = tokens.Dequeue(); if (next.TokenType == Token.LEFTCURLYBRACKET) { openbrackets++; } else if (next.TokenType == Token.RIGHTCURLYBRACKET) { openbrackets--; } temptokens.Enqueue(next); } while (openbrackets > 0); //Call back into the Query Parser to try and Parse the Graph Pattern for the Function SparqlQueryParserContext tempcontext = new SparqlQueryParserContext(temptokens); tempcontext.Query.NamespaceMap.Import(this._nsmapper); tempcontext.Query.BaseUri = this._baseUri; return new ExistsFunction(this._parser.TryParseGraphPattern(tempcontext, true), mustExist); default: throw Error("Unexpected Token '" + next.GetType().ToString() + "' encountered while trying to parse a Built-in Function call", next); } }
private void TryParseSubquery(SparqlQueryParserContext context, GraphPattern p) { if (context.SyntaxMode == SparqlQuerySyntax.Sparql_1_0) throw new RdfParseException("Sub-queries are not supported in SPARQL 1.0"); //We're going to make a temporary Token Queue which we will populate and then //use to create a new SPARQL Query Parser Context NonTokenisedTokenQueue tokens = new NonTokenisedTokenQueue(); //Assume we've already seen a SELECT tokens.Enqueue(new BOFToken()); tokens.Enqueue(new SelectKeywordToken(1, 1)); //Now collect Tokens until we hit the closing Right Bracket int openBrackets = 1; IToken next; do { next = context.Tokens.Peek(); if (next.TokenType == Token.LEFTCURLYBRACKET) { openBrackets++; } else if (next.TokenType == Token.RIGHTCURLYBRACKET) { openBrackets--; } else if (next.TokenType == Token.EOF) { throw ParserHelper.Error("Unexpected End of File encountered while trying to gather Tokens to parse a Sub-Query from", next); } if (openBrackets > 0) { tokens.Enqueue(context.Tokens.Dequeue()); } } while (openBrackets > 0); tokens.Enqueue(new EOFToken(0, 0)); //Create a Sub-query Parser Context SparqlQueryParserContext subcontext = new SparqlQueryParserContext(context, tokens); subcontext.Query.NamespaceMap.Import(context.Query.NamespaceMap); SparqlQuery subquery = this.ParseInternal(subcontext); foreach (SparqlVariable var in subquery.Variables) { if (var.IsResultVariable) context.Query.AddVariable("?" + var.Name, false); } SubQueryPattern subqueryPattern = new SubQueryPattern(subquery); p.AddTriplePattern(subqueryPattern); }