/* -*- Mode: c; c-basic-offset: 2 -*- * * sparql_parser.y - Rasqal SPARQL parser over tokens from sparql_lexer.l * * $Id: sparql_parser.y 11387 2006-10-06 06:21:38Z dajobe $ * * Copyright (C) 2004-2006, David Beckett http://purl.org/net/dajobe/ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/ * * This package is Free Software and part of Redland http://librdf.org/ * * It is licensed under the following three licenses as alternatives: * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version * 2. GNU General Public License (GPL) V2 or any newer version * 3. Apache License, V2.0 or any newer version * * You may not use this file except in compliance with at least one of * the above three licenses. * * See LICENSE.html or LICENSE.txt at the top of this package for the * complete terms and further detail along with the license texts for * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively. * * References: * SPARQL Query Language for RDF, W3C Candidate Recommendation 6 April 2006 * http://www.w3.org/TR/2006/CR-rdf-sparql-query-20060406/ * * Editor's draft of above http://www.w3.org/2001/sw/DataAccess/rq23/ * */ %{ #ifdef HAVE_CONFIG_H #include #endif #ifdef WIN32 #include #endif #include #include #include #include #include #define YY_DECL int sparql_lexer_lex (YYSTYPE *sparql_parser_lval, yyscan_t yyscanner) #define YY_NO_UNISTD_H 1 #include #include /* #undef RASQAL_DEBUG #define RASQAL_DEBUG 2 */ #define DEBUG_FH stdout /* Make verbose error messages for syntax errors */ #define YYERROR_VERBOSE 1 /* Slow down the grammar operation and watch it work */ #if RASQAL_DEBUG > 2 #define YYDEBUG 1 #endif /* the lexer does not seem to track this */ #undef RASQAL_SPARQL_USE_ERROR_COLUMNS /* Missing sparql_lexer.c/h prototypes */ int sparql_lexer_get_column(yyscan_t yyscanner); /* Not used here */ /* void sparql_lexer_set_column(int column_no , yyscan_t yyscanner);*/ /* What the lexer wants */ extern int sparql_lexer_lex (YYSTYPE *sparql_parser_lval, yyscan_t scanner); #define YYLEX_PARAM ((rasqal_sparql_query_engine*)(((rasqal_query*)rq)->context))->scanner /* Pure parser argument (a void*) */ #define YYPARSE_PARAM rq /* Make the yyerror below use the rdf_parser */ #undef yyerror #define yyerror(message) sparql_query_error((rasqal_query*)rq, message) /* Make lex/yacc interface as small as possible */ #undef yylex #define yylex sparql_lexer_lex static int sparql_parse(rasqal_query* rq, const unsigned char *string); static void sparql_query_error(rasqal_query* rq, const char *message); static void sparql_query_error_full(rasqal_query *rq, const char *message, ...) RASQAL_PRINTF_FORMAT(2, 3); static int sparql_is_builtin_xsd_datatype(raptor_uri* uri); %} /* directives */ %pure-parser /* Interface between lexer and parser */ %union { raptor_sequence *seq; rasqal_variable *variable; rasqal_literal *literal; rasqal_triple *triple; rasqal_expression *expr; rasqal_graph_pattern *graph_pattern; double floating; raptor_uri *uri; unsigned char *name; rasqal_formula *formula; } /* * shift/reduce conflicts * FIXME: document this */ %expect 12 /* word symbols */ %token SELECT FROM WHERE %token OPTIONAL DESCRIBE CONSTRUCT ASK DISTINCT LIMIT UNION %token PREFIX BASE BOUND %token GRAPH NAMED FILTER OFFSET ORDER BY REGEX ASC DESC LANGMATCHES %token A "a" %token STR "str" %token LANG "lang" %token DATATYPE "datatype" %token ISURI "isUri" %token ISBLANK "isBlank" %token ISLITERAL "isLiteral" /* expression delimitors */ %token ',' '(' ')' '[' ']' '{' '}' %token '?' '$' /* SC booleans */ %left SC_OR "||" %left SC_AND "&&" /* operations */ %left EQ "=" %left NEQ "!=" %left LT "<" %left GT ">" %left LE "<=" %left GE ">=" /* arithmetic operations */ %left '+' '-' '*' '/' /* unary operations */ /* literals */ %token FLOATING_POINT_LITERAL "floating point literal" %token STRING_LITERAL "string literal" %token INTEGER_LITERAL "integer literal" %token BOOLEAN_LITERAL "boolean literal" %token DECIMAL_LITERAL "decimal literal" %token URI_LITERAL "URI literal" %token URI_LITERAL_BRACE "URI literal (" %token QNAME_LITERAL "QName literal" %token QNAME_LITERAL_BRACE "QName literal (" %token BLANK_LITERAL "blank node literal" %token IDENTIFIER "identifier" %type SelectQuery ConstructQuery DescribeQuery %type VarList VarOrIRIrefList ArgList ConstructTriplesOpt %type ConstructTemplate OrderConditionList %type GraphNodeListNotEmpty %type TriplesSameSubject TriplesSameSubjectDotListOpt %type PropertyList PropertyListTailOpt PropertyListNotEmpty %type ObjectList ObjectTail Collection %type VarOrTerm Verb GraphNode TriplesNode %type BlockOfTriplesOpt BlankNodePropertyList %type GroupGraphPattern GraphPattern %type GraphGraphPattern OptionalGraphPattern %type GroupOrUnionGraphPattern GroupOrUnionGraphPatternList %type GraphPatternNotTriples %type FilteredBasicGraphPattern %type Expression ConditionalOrExpression ConditionalAndExpression %type RelationalExpression AdditiveExpression %type MultiplicativeExpression UnaryExpression %type BuiltInCall RegexExpression FunctionCall %type BrackettedExpression PrimaryExpression %type OrderCondition Constraint %type GraphTerm IRIref BlankNode %type VarOrIRIref VarOrBlankNodeOrIRIref %type IRIrefBrace %type Var %destructor { rasqal_free_literal($$); } FLOATING_POINT_LITERAL STRING_LITERAL INTEGER_LITERAL BOOLEAN_LITERAL DECIMAL_LITERAL %destructor { raptor_free_uri($$); } URI_LITERAL URI_LITERAL_BRACE %destructor { RASQAL_FREE(cstring, $$); } QNAME_LITERAL QNAME_LITERAL_BRACE BLANK_LITERAL IDENTIFIER %% /* Below here, grammar terms are numbered from * http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/ * except where noted */ /* SPARQL Grammar: [1] Query */ Query: Prolog ReportFormat DatasetClauseOpt WhereClauseOpt OrderClauseOpt LimitClauseOpt OffsetClauseOpt { } ; /* NEW Grammar Term pulled out of [1] Query */ ReportFormat: SelectQuery { ((rasqal_query*)rq)->selects=$1; ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_SELECT; } | ConstructQuery { ((rasqal_query*)rq)->constructs=$1; ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_CONSTRUCT; } | DescribeQuery { ((rasqal_query*)rq)->describes=$1; ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_DESCRIBE; } | AskQuery { ((rasqal_query*)rq)->verb=RASQAL_QUERY_VERB_ASK; } ; /* SPARQL Grammar: [2] Prolog */ Prolog: BaseDeclOpt PrefixDeclOpt { /* nothing to do */ } ; /* SPARQL Grammar: [3] BaseDecl */ BaseDeclOpt: BASE URI_LITERAL { if(((rasqal_query*)rq)->base_uri) raptor_free_uri(((rasqal_query*)rq)->base_uri); ((rasqal_query*)rq)->base_uri=$2; } | /* empty */ { /* nothing to do */ } ; /* SPARQL Grammar: [4] PrefixDecl */ PrefixDeclOpt: PrefixDeclOpt PREFIX IDENTIFIER URI_LITERAL { raptor_sequence *seq=((rasqal_query*)rq)->prefixes; unsigned const char* prefix_string=$3; size_t l=0; if(prefix_string) l=strlen((const char*)prefix_string); if(raptor_namespaces_find_namespace(((rasqal_query*)rq)->namespaces, prefix_string, l)) { /* A prefix may be defined only once */ sparql_syntax_warning(((rasqal_query*)rq), "PREFIX %s can be defined only once.", prefix_string ? (const char*)prefix_string : ":"); } else { rasqal_prefix *p=rasqal_new_prefix(prefix_string, $4); raptor_sequence_push(seq, p); rasqal_query_declare_prefix(((rasqal_query*)rq), p); } } | /* empty */ { /* nothing to do, rq->prefixes already initialised */ } ; /* SPARQL Grammar: [5] SelectQuery */ SelectQuery: SELECT DISTINCT VarList { $$=$3; ((rasqal_query*)rq)->distinct=1; } | SELECT DISTINCT '*' { $$=NULL; ((rasqal_query*)rq)->wildcard=1; ((rasqal_query*)rq)->distinct=1; } | SELECT VarList { $$=$2; } | SELECT '*' { $$=NULL; ((rasqal_query*)rq)->wildcard=1; } ; /* NEW Grammar Term pulled out of [5] SelectQuery */ VarList: VarList Var { $$=$1; raptor_sequence_push($$, $2); } | VarList ',' Var { $$=$1; raptor_sequence_push($$, $3); } | Var { /* The variables are freed from the raptor_query field variables */ $$=raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_variable_print); raptor_sequence_push($$, $1); } ; /* SPARQL Grammar: [6] DescribeQuery */ DescribeQuery: DESCRIBE VarOrIRIrefList { $$=$2; } | DESCRIBE '*' { $$=NULL; } ; /* NEW Grammar Term pulled out of [6] DescribeQuery */ VarOrIRIrefList: VarOrIRIrefList VarOrIRIref { $$=$1; raptor_sequence_push($$, $2); } | VarOrIRIrefList ',' VarOrIRIref { $$=$1; raptor_sequence_push($$, $3); } | VarOrIRIref { $$=raptor_new_sequence(NULL, (raptor_sequence_print_handler*)rasqal_literal_print); raptor_sequence_push($$, $1); } ; /* SPARQL Grammar: [7] ConstructQuery */ ConstructQuery: CONSTRUCT ConstructTemplate { $$=$2; } | CONSTRUCT '*' { $$=NULL; ((rasqal_query*)rq)->wildcard=1; } ; /* SPARQL Grammar: [8] AskQuery */ AskQuery: ASK { /* nothing to do */ } /* SPARQL Grammar: [9] DatasetClause */ DatasetClauseOpt: DatasetClauseOpt FROM DefaultGraphClause | DatasetClauseOpt FROM NamedGraphClause | /* empty */ ; /* SPARQL Grammar: [10] DefaultGraphClause */ DefaultGraphClause: IRIref { if($1) { raptor_uri* uri=rasqal_literal_as_uri($1); rasqal_query_add_data_graph((rasqal_query*)rq, uri, uri, RASQAL_DATA_GRAPH_BACKGROUND); rasqal_free_literal($1); } } ; /* SPARQL Grammar: [11] NamedGraphClause */ NamedGraphClause: NAMED IRIref { if($2) { raptor_uri* uri=rasqal_literal_as_uri($2); rasqal_query_add_data_graph((rasqal_query*)rq, uri, uri, RASQAL_DATA_GRAPH_NAMED); rasqal_free_literal($2); } } ; /* SPARQL Grammar: [12] SourceSelector - junk */ /* SPARQL Grammar: [13] WhereClause - remained for clarity */ WhereClauseOpt: WHERE GroupGraphPattern { ((rasqal_query*)rq)->query_graph_pattern=$2; } | GroupGraphPattern { sparql_syntax_warning(((rasqal_query*)rq), "WHERE omitted"); ((rasqal_query*)rq)->query_graph_pattern=$1; } | /* empty */ ; /* SPARQL Grammar: [14] SolutionModifier - merged into SelectQuery etc. */ /* SPARQL Grammar: [15] OrderClause - remained for clarity */ OrderClauseOpt: ORDER BY OrderConditionList { if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) { sparql_query_error((rasqal_query*)rq, "ORDER BY cannot be used with ASK"); } else { ((rasqal_query*)rq)->order_conditions_sequence=$3; } } | /* empty */ ; /* NEW Grammar Term pulled out of [16] OrderClauseOpt */ OrderConditionList: OrderConditionList OrderCondition { $$=$1; if($2) raptor_sequence_push($$, $2); } | OrderCondition { $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print); if($1) raptor_sequence_push($$, $1); } ; /* SPARQL Grammar: [16] OrderCondition */ OrderCondition: ASC BrackettedExpression { $$=rasqal_new_1op_expression(RASQAL_EXPR_ORDER_COND_ASC, $2); } | DESC BrackettedExpression { $$=rasqal_new_1op_expression(RASQAL_EXPR_ORDER_COND_DESC, $2); } | FunctionCall { /* The direction of ordering is ascending by default */ $$=rasqal_new_1op_expression(RASQAL_EXPR_ORDER_COND_ASC, $1); } | Var { rasqal_literal* l=rasqal_new_variable_literal($1); rasqal_expression *e=rasqal_new_literal_expression(l); /* The direction of ordering is ascending by default */ $$=rasqal_new_1op_expression(RASQAL_EXPR_ORDER_COND_ASC, e); } | BrackettedExpression { /* The direction of ordering is ascending by default */ $$=rasqal_new_1op_expression(RASQAL_EXPR_ORDER_COND_ASC, $1); } ; /* SPARQL Grammar: [17] LimitClause - remained for clarity */ LimitClauseOpt: LIMIT INTEGER_LITERAL { if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) { sparql_query_error((rasqal_query*)rq, "LIMIT cannot be used with ASK"); } else { if($2 != NULL) { ((rasqal_query*)rq)->limit=$2->value.integer; rasqal_free_literal($2); } } } | /* empty */ ; /* SPARQL Grammar: [18] OffsetClause - remained for clarity */ OffsetClauseOpt: OFFSET INTEGER_LITERAL { if(((rasqal_query*)rq)->verb == RASQAL_QUERY_VERB_ASK) { sparql_query_error((rasqal_query*)rq, "LIMIT cannot be used with ASK"); } else { if($2 != NULL) { ((rasqal_query*)rq)->offset=$2->value.integer; rasqal_free_literal($2); } } } | /* empty */ ; /* SPARQL Grammar: [19] GroupGraphPattern */ GroupGraphPattern: '{' GraphPattern '}' { $$=$2; } /* NEW Grammar Term */ DotOptional: '.' | /* empty */ ; /* SPARQL Grammar: [20] GraphPattern */ GraphPattern: FilteredBasicGraphPattern GraphPatternNotTriples DotOptional GraphPattern { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "GraphPattern 1\n FilteredBasicGraphPattern="); if($1) rasqal_graph_pattern_print($1, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, ", GraphPatternNotTriples="); if($2) rasqal_graph_pattern_print($2, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, ", GraphPattern="); if($4) rasqal_graph_pattern_print($4, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n", DEBUG_FH); #endif $$=$4; /* push ($1,$2) to start of $4 graph sequence */ if($2) raptor_sequence_shift($$->graph_patterns, $2); if($1) raptor_sequence_shift($$->graph_patterns, $1); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after grouping graph pattern="); if($$) rasqal_graph_pattern_print($$, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } | FilteredBasicGraphPattern { raptor_sequence *seq; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "GraphPattern 2\n FilteredBasicGraphPattern="); if($1) rasqal_graph_pattern_print($1, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n", DEBUG_FH); #endif seq=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print); if($1) raptor_sequence_push(seq, $1); $$=rasqal_new_graph_pattern_from_sequence((rasqal_query*)rq, seq, RASQAL_GRAPH_PATTERN_OPERATOR_GROUP); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after grouping graph pattern="); if($$) rasqal_graph_pattern_print($$, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } ; /* SPARQL Grammar Term [21] FilteredBasicGraphPattern */ FilteredBasicGraphPattern: BlockOfTriplesOpt Constraint DotOptional FilteredBasicGraphPattern { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "FilteredBasicGraphPattern 1\n BlockOfTriplesOpt="); if($1) rasqal_formula_print($1, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, ", Constraint="); if($2) rasqal_expression_print($2, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, ", FilteredBasicGraphPattern="); if($4) rasqal_graph_pattern_print($4, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n", DEBUG_FH); #endif $$=$4; /* push $1 to start of $4 graph sequence */ if($1) { rasqal_graph_pattern *gp; gp=rasqal_engine_new_graph_pattern_from_formula((rasqal_query*)rq, $1, RASQAL_GRAPH_PATTERN_OPERATOR_BASIC); raptor_sequence_shift($$->graph_patterns, gp); } if($2) rasqal_graph_pattern_add_constraint($$, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after grouping graph pattern="); if($$) rasqal_graph_pattern_print($$, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } | BlockOfTriplesOpt { rasqal_graph_pattern *formula_gp=NULL; raptor_sequence *seq; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "FilteredBasicGraphPattern 2\n BlockOfTriplesOpt="); if($1) rasqal_formula_print($1, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n", DEBUG_FH); #endif if($1) formula_gp=rasqal_engine_new_graph_pattern_from_formula((rasqal_query*)rq, $1, RASQAL_GRAPH_PATTERN_OPERATOR_BASIC); seq=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print); if(formula_gp) raptor_sequence_push(seq, formula_gp); $$=rasqal_new_graph_pattern_from_sequence((rasqal_query*)rq, seq, RASQAL_GRAPH_PATTERN_OPERATOR_GROUP); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after, group graph pattern="); if($$) rasqal_graph_pattern_print($$, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } ; /* SPARQL Grammar: [22] BlockOfTriples */ BlockOfTriplesOpt: TriplesSameSubject TriplesSameSubjectDotListOpt { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "BlockOfTriplesOpt\n TriplesSameSubject="); if($1) rasqal_formula_print($1, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs(" TriplesSameSubjectDotListOpt=", DEBUG_FH); if($2) rasqal_formula_print($2, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n", DEBUG_FH); #endif /* $1 and $2 are freed as necessary */ $$=rasqal_formula_join($1, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after joining formula="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } | /* empty */ { $$=NULL; } ; /* New Grammar Term pulled out of [22] BlockOfTriples * ( '.' TriplesSameSubject? )* */ TriplesSameSubjectDotListOpt: TriplesSameSubjectDotListOpt TriplesSameSubject { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "TriplesSameSubjectDotTriplesOpt\n TriplesSameSubjectDotListOpt="); if($1) rasqal_formula_print($1, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs(" TriplesSameSubject=", DEBUG_FH); if($2) rasqal_formula_print($2, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n", DEBUG_FH); #endif /* $1 and $2 are freed as necessary */ $$=rasqal_formula_join($1, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after joining formula="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } | TriplesSameSubjectDotListOpt '.' { $$=$1; } | /* empty */ { $$=NULL; } ; /* SPARQL Grammar: [23] GraphPatternNotTriples */ GraphPatternNotTriples: OptionalGraphPattern { $$=$1; } | GroupOrUnionGraphPattern { $$=$1; } | GraphGraphPattern { $$=$1; } ; /* SPARQL Grammar: [24] OptionalGraphPattern */ OptionalGraphPattern: OPTIONAL GroupGraphPattern { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "PatternElementForms 4\n graphpattern="); if($2) rasqal_graph_pattern_print($2, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n\n", DEBUG_FH); #endif if($2) $2->op = RASQAL_GRAPH_PATTERN_OPERATOR_OPTIONAL; $$=$2; } ; /* SPARQL Grammar: [25] GraphGraphPattern */ GraphGraphPattern: GRAPH VarOrBlankNodeOrIRIref GroupGraphPattern { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "GraphGraphPattern 2\n varoruri="); rasqal_literal_print($2, DEBUG_FH); fprintf(DEBUG_FH, ", graphpattern="); if($3) rasqal_graph_pattern_print($3, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputs("\n\n", DEBUG_FH); #endif if($3) { rasqal_graph_pattern_set_origin($3, $2); $3->op = RASQAL_GRAPH_PATTERN_OPERATOR_GRAPH; } rasqal_free_literal($2); $$=$3; } ; /* SPARQL Grammar: [26] GroupOrUnionGraphPattern */ GroupOrUnionGraphPattern: GroupGraphPattern UNION GroupOrUnionGraphPatternList { $$=$3; raptor_sequence_push($$->graph_patterns, $1); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "UnionGraphPattern\n graphpattern="); rasqal_graph_pattern_print($$, DEBUG_FH); fputs("\n\n", DEBUG_FH); #endif } | GroupGraphPattern { $$=$1; } ; /* NEW Grammar Term pulled out of [26] GroupOrUnionGraphPattern */ GroupOrUnionGraphPatternList: GroupOrUnionGraphPatternList UNION GroupGraphPattern { $$=$1; if($3) raptor_sequence_push($$->graph_patterns, $3); } | GroupGraphPattern { raptor_sequence *seq; seq=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_graph_pattern, (raptor_sequence_print_handler*)rasqal_graph_pattern_print); if($1) raptor_sequence_push(seq, $1); $$=rasqal_new_graph_pattern_from_sequence((rasqal_query*)rq, seq, RASQAL_GRAPH_PATTERN_OPERATOR_UNION); } ; /* SPARQL Grammar: [27] Constraint */ Constraint: FILTER BrackettedExpression { $$=$2; } | FILTER BuiltInCall { $$=$2; } | FILTER FunctionCall { $$=$2; } ; /* SPARQL Grammar: [28] FunctionCall */ FunctionCall: IRIrefBrace ArgList ')' { raptor_uri* uri=rasqal_literal_as_uri($1); uri=raptor_uri_copy(uri); if(!$2) $2=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print); if(raptor_sequence_size($2) == 1 && sparql_is_builtin_xsd_datatype(uri)) { rasqal_expression* e=(rasqal_expression*)raptor_sequence_pop($2); $$=rasqal_new_cast_expression(uri, e); raptor_free_sequence($2); } else $$=rasqal_new_function_expression(uri, $2); rasqal_free_literal($1); } ; /* SPARQL Grammar: [29] ArgList */ ArgList: ArgList ',' Expression { $$=$1; if($3) raptor_sequence_push($$, $3); } | Expression { $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_expression, (raptor_sequence_print_handler*)rasqal_expression_print); if($1) raptor_sequence_push($$, $1); } | /* empty */ { $$=NULL; } ; /* SPARQL Grammar: [30] ConstructTemplate */ ConstructTemplate: '{' ConstructTriplesOpt '}' { $$=$2; } ; /* SPARQL Grammar: [31] ConstructTriples renamed for clarity */ ConstructTriplesOpt: TriplesSameSubject '.' ConstructTriplesOpt { $$=NULL; if($1) { $$=$1->triples; $1->triples=NULL; rasqal_free_formula($1); } if($3) { if(!$$) $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print); raptor_sequence_join($$, $3); raptor_free_sequence($3); } } | TriplesSameSubject { $$=NULL; if($1) { $$=$1->triples; $1->triples=NULL; rasqal_free_formula($1); } } | /* empty */ { $$=NULL; } ; /* SPARQL Grammar: [32] TriplesSameSubject */ TriplesSameSubject: VarOrTerm PropertyListNotEmpty { int i; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "TriplesSameSubject 1\n subject="); rasqal_formula_print($1, DEBUG_FH); if($2) { fprintf(DEBUG_FH, "\n propertyList="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); } else fprintf(DEBUG_FH, "\n and empty propertyList\n"); #endif if($2) { raptor_sequence *seq=$2->triples; rasqal_literal *subject=$1->value; /* non-empty property list, handle it */ for(i=0; i < raptor_sequence_size(seq); i++) { rasqal_triple* t2=(rasqal_triple*)raptor_sequence_get_at(seq, i); if(t2->subject) continue; t2->subject=rasqal_new_literal_from_literal(subject); } #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after substitution propertyList="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif } $$=rasqal_formula_join($1, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after joining formula="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } | TriplesNode PropertyList { int i; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "TriplesSameSubject 2\n subject="); rasqal_formula_print($1, DEBUG_FH); if($2) { fprintf(DEBUG_FH, "\n propertyList="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); } else fprintf(DEBUG_FH, "\n and empty propertyList\n"); #endif if($2) { raptor_sequence *seq=$2->triples; rasqal_literal *subject=$1->value; /* non-empty property list, handle it */ for(i=0; i < raptor_sequence_size(seq); i++) { rasqal_triple* t2=(rasqal_triple*)raptor_sequence_get_at(seq, i); if(t2->subject) continue; t2->subject=rasqal_new_literal_from_literal(subject); } #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after substitution propertyList="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif } $$=rasqal_formula_join($1, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after joining formula="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } ; /* SPARQL Grammar: [33] PropertyList */ PropertyList: PropertyListNotEmpty { $$=$1; } | /* empty */ { $$=NULL; } ; /* SPARQL Grammar: [34] PropertyListNotEmpty */ PropertyListNotEmpty: Verb ObjectList PropertyListTailOpt { int i; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "PropertyList 1\n Verb="); rasqal_formula_print($1, DEBUG_FH); fprintf(DEBUG_FH, "\n ObjectList="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n PropertyListTail="); if($3 != NULL) rasqal_formula_print($3, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif if($2 == NULL) { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " empty ObjectList not processed\n"); #endif } else if($1 && $2) { raptor_sequence *seq=$2->triples; rasqal_literal *predicate=$1->value; rasqal_formula *formula; /* non-empty property list, handle it */ for(i=0; ipredicate) t2->predicate=(rasqal_literal*)rasqal_new_literal_from_literal(predicate); } #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after substitution ObjectList="); raptor_sequence_print(seq, DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif formula=rasqal_new_formula(); formula->triples=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print); for(i=0; i < raptor_sequence_size(seq); i++) { rasqal_triple* t2=(rasqal_triple*)raptor_sequence_get_at(seq, i); raptor_sequence_push(formula->triples, t2); } while(raptor_sequence_size(seq)) raptor_sequence_pop(seq); $3=rasqal_formula_join(formula, $3); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after appending ObjectList="); rasqal_formula_print($3, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif rasqal_free_formula($2); } if($1) rasqal_free_formula($1); $$=$3; } ; /* NEW Grammar Term pulled out of [34] PropertyListNotEmpty */ PropertyListTailOpt: ';' PropertyList { $$=$2; } | /* empty */ { $$=NULL; } ; /* SPARQL Grammar: [35] ObjectList */ ObjectList: GraphNode ObjectTail { rasqal_formula *formula=NULL; rasqal_triple *triple; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "ObjectList 1\n"); fprintf(DEBUG_FH, " GraphNode=\n"); rasqal_formula_print($1, DEBUG_FH); fprintf(DEBUG_FH, "\n"); if($2) { fprintf(DEBUG_FH, " ObjectTail="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); } else fprintf(DEBUG_FH, " and empty ObjectTail\n"); #endif formula=rasqal_new_formula(); triple=rasqal_new_triple(NULL, NULL, $1->value); $1->value=NULL; formula->triples=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print); raptor_sequence_push(formula->triples, triple); $$=rasqal_formula_join(formula, $1); $$=rasqal_formula_join(formula, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " objectList is now "); if($$) raptor_sequence_print($$->triples, DEBUG_FH); else fputs("NULL", DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } ; /* NEW Grammar Term pulled out of [35] ObjectList */ ObjectTail: ',' ObjectList { $$=$2; } | /* empty */ { $$=NULL; } ; /* SPARQL Grammar: [36] Verb */ Verb: VarOrBlankNodeOrIRIref { $$=rasqal_new_formula(); $$->value=$1; } | A { raptor_uri *uri; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "verb Verb=rdf:type (a)\n"); #endif uri=raptor_new_uri_for_rdf_concept("type"); $$=rasqal_new_formula(); $$->value=rasqal_new_uri_literal(uri); } ; /* SPARQL Grammar: [37] TriplesNode */ TriplesNode: Collection { $$=$1; } | BlankNodePropertyList { $$=$1; } ; /* SPARQL Grammar: [38] BlankNodePropertyList */ BlankNodePropertyList: '[' PropertyListNotEmpty ']' { int i; const unsigned char *id=rasqal_query_generate_bnodeid((rasqal_query*)rq, NULL); if($2 == NULL) $$=rasqal_new_formula(); else { $$=$2; if($$->value) rasqal_free_literal($$->value); } $$->value=rasqal_new_simple_literal(RASQAL_LITERAL_BLANK, id); if($2 == NULL) { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "TriplesNode\n PropertyList="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif } else { raptor_sequence *seq=$2->triples; /* non-empty property list, handle it */ #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "TriplesNode\n PropertyList="); raptor_sequence_print(seq, DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif for(i=0; isubject) continue; t2->subject=(rasqal_literal*)rasqal_new_literal_from_literal($$->value); } #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after substitution formula="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } } ; /* SPARQL Grammar: [39] Collection (allowing empty case) */ Collection: '(' GraphNodeListNotEmpty ')' { int i; rasqal_query* rdf_query=(rasqal_query*)rq; rasqal_literal* first_identifier; rasqal_literal* rest_identifier; rasqal_literal* object; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "Collection\n GraphNodeListNotEmpty="); raptor_sequence_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); #endif first_identifier=rasqal_new_uri_literal(raptor_uri_copy(rasqal_rdf_first_uri)); rest_identifier=rasqal_new_uri_literal(raptor_uri_copy(rasqal_rdf_rest_uri)); object=rasqal_new_uri_literal(raptor_uri_copy(rasqal_rdf_nil_uri)); $$=rasqal_new_formula(); $$->triples=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_triple, (raptor_sequence_print_handler*)rasqal_triple_print); for(i=raptor_sequence_size($2)-1; i>=0; i--) { rasqal_formula* f=(rasqal_formula*)raptor_sequence_get_at($2, i); const unsigned char *blank_id=rasqal_query_generate_bnodeid(rdf_query, NULL); rasqal_literal* blank=rasqal_new_simple_literal(RASQAL_LITERAL_BLANK, blank_id); rasqal_triple *t2; /* Move existing formula triples */ if(f->triples) raptor_sequence_join($$->triples, f->triples); /* add new triples we needed */ t2=rasqal_new_triple(rasqal_new_literal_from_literal(blank), rasqal_new_literal_from_literal(first_identifier), rasqal_new_literal_from_literal(f->value)); raptor_sequence_push($$->triples, t2); t2=rasqal_new_triple(rasqal_new_literal_from_literal(blank), rasqal_new_literal_from_literal(rest_identifier), rasqal_new_literal_from_literal(object)); raptor_sequence_push($$->triples, t2); rasqal_free_literal(object); object=blank; } $$->value=object; #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " after substitution collection="); rasqal_formula_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif rasqal_free_literal(first_identifier); rasqal_free_literal(rest_identifier); } ; /* NEW Grammar Term pulled out of [39] Collection */ /* Sequence of formula */ GraphNodeListNotEmpty: GraphNodeListNotEmpty GraphNode { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "GraphNodeListNotEmpty 1\n"); if($2) { fprintf(DEBUG_FH, " GraphNode="); rasqal_formula_print($2, DEBUG_FH); fprintf(DEBUG_FH, "\n"); } else fprintf(DEBUG_FH, " and empty GraphNode\n"); if($1) { fprintf(DEBUG_FH, " GraphNodeListNotEmpty="); raptor_sequence_print($1, DEBUG_FH); fprintf(DEBUG_FH, "\n"); } else fprintf(DEBUG_FH, " and empty GraphNodeListNotEmpty\n"); #endif if(!$2) $$=NULL; else { raptor_sequence_push($$, $2); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " itemList is now "); raptor_sequence_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } } | GraphNode { #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, "GraphNodeListNotEmpty 2\n"); if($1) { fprintf(DEBUG_FH, " GraphNode="); rasqal_formula_print($1, DEBUG_FH); fprintf(DEBUG_FH, "\n"); } else fprintf(DEBUG_FH, " and empty GraphNode\n"); #endif $$=NULL; if($1) $$=raptor_new_sequence((raptor_sequence_free_handler*)rasqal_free_formula, (raptor_sequence_print_handler*)rasqal_formula_print); raptor_sequence_push($$, $1); #if RASQAL_DEBUG > 1 fprintf(DEBUG_FH, " GraphNodeListNotEmpty is now "); raptor_sequence_print($$, DEBUG_FH); fprintf(DEBUG_FH, "\n\n"); #endif } ; /* SPARQL Grammar: [40] GraphNode */ GraphNode: VarOrTerm { $$=$1; } | TriplesNode { $$=$1; } ; /* SPARQL Grammar Term: [41] VarOrTerm */ VarOrTerm: Var { $$=rasqal_new_formula(); $$->value=rasqal_new_variable_literal($1); } | GraphTerm { $$=rasqal_new_formula(); $$->value=$1; } ; /* SPARQL Grammar: [42] VarOrIRIref */ VarOrIRIref: Var { $$=rasqal_new_variable_literal($1); } | IRIref { $$=$1; } ; /* SPARQL Grammar Term: [43] VarOrBlankNodeOrIRIref */ VarOrBlankNodeOrIRIref: Var { $$=rasqal_new_variable_literal($1); } | BlankNode { $$=$1; } | IRIref { $$=$1; } ; /* SPARQL Grammar: [44] Var */ Var: '?' IDENTIFIER { $$=rasqal_new_variable((rasqal_query*)rq, $2, NULL); } | '$' IDENTIFIER { $$=rasqal_new_variable((rasqal_query*)rq, $2, NULL); } ; /* SPARQL Grammar: [45] GraphTerm */ /* + and - for numerics is in the lexer */ GraphTerm: IRIref { $$=$1; } | INTEGER_LITERAL { $$=$1; } | FLOATING_POINT_LITERAL { $$=$1; } | DECIMAL_LITERAL { $$=$1; } | STRING_LITERAL { $$=$1; } | BOOLEAN_LITERAL { $$=$1; } | BlankNode { $$=$1; } | '(' ')' { $$=rasqal_new_uri_literal(raptor_uri_copy(rasqal_rdf_nil_uri)); } ; /* SPARQL Grammar: [46] Expression */ Expression: ConditionalOrExpression { $$=$1; } ; /* SPARQL Grammar: [47] ConditionalOrExpression */ ConditionalOrExpression: ConditionalOrExpression SC_OR ConditionalAndExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_OR, $1, $3); } | ConditionalAndExpression { $$=$1; } ; /* SPARQL Grammar: [48] ConditionalAndExpression */ ConditionalAndExpression: ConditionalAndExpression SC_AND RelationalExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_AND, $1, $3); ; } | RelationalExpression { $$=$1; } ; /* SPARQL Grammar: [49] ValueLogical - merged into RelationalExpression */ /* SPARQL Grammar: [50] RelationalExpression */ RelationalExpression: AdditiveExpression EQ AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_EQ, $1, $3); } | AdditiveExpression NEQ AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_NEQ, $1, $3); } | AdditiveExpression LT AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_LT, $1, $3); } | AdditiveExpression GT AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_GT, $1, $3); } | AdditiveExpression LE AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_LE, $1, $3); } | AdditiveExpression GE AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_GE, $1, $3); } | AdditiveExpression { $$=$1; } ; /* SPARQL Grammar: [51] NumericExpression - merged into AdditiveExpression */ /* SPARQL Grammar: [52] AdditiveExpression */ AdditiveExpression: MultiplicativeExpression '+' AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_PLUS, $1, $3); } | MultiplicativeExpression '-' AdditiveExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_MINUS, $1, $3); } | MultiplicativeExpression { $$=$1; } ; /* SPARQL Grammar: [53] MultiplicativeExpression */ MultiplicativeExpression: UnaryExpression '*' MultiplicativeExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_STAR, $1, $3); } | UnaryExpression '/' MultiplicativeExpression { $$=rasqal_new_2op_expression(RASQAL_EXPR_SLASH, $1, $3); } | UnaryExpression { $$=$1; } ; /* SPARQL Grammar: [54] UnaryExpression */ UnaryExpression: '!' PrimaryExpression { $$=rasqal_new_1op_expression(RASQAL_EXPR_BANG, $2); } | '+' PrimaryExpression { $$=$2; } | '-' PrimaryExpression { $$=rasqal_new_1op_expression(RASQAL_EXPR_UMINUS, $2); } | PrimaryExpression { $$=$1; } ; /* SPARQL Grammar: [55] PrimaryExpression * == BrackettedExpression | BuiltInCall | IRIrefOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | Var * == BrackettedExpression | BuiltInCall | IRIref ArgList? | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | Var * == BrackettedExpression | BuiltInCall | FunctionCall | * approximately GraphTerm | Var * */ PrimaryExpression: BrackettedExpression { $$=$1; } | BuiltInCall { $$=$1; } | FunctionCall { /* Grammar has IRIrefOrFunction here which is "IRIref ArgList?" * and essentially shorthand for FunctionCall | IRIref. The Rasqal * SPARQL lexer distinguishes these for us with IRIrefBrace. * IRIref is covered below by GraphTerm. */ $$=$1; } | GraphTerm { $$=rasqal_new_literal_expression($1); } | Var { rasqal_literal *l=rasqal_new_variable_literal($1); $$=rasqal_new_literal_expression(l); } ; /* SPARQL Grammar: [56] BrackettedExpression */ BrackettedExpression: '(' Expression ')' { $$=$2; } ; /* SPARQL Grammar: [57] BuiltInCall */ BuiltInCall: STR '(' Expression ')' { $$=rasqal_new_1op_expression(RASQAL_EXPR_STR, $3); } | LANG '(' Expression ')' { $$=rasqal_new_1op_expression(RASQAL_EXPR_LANG, $3); } | LANGMATCHES '(' Expression ',' Expression ')' { $$=rasqal_new_2op_expression(RASQAL_EXPR_LANGMATCHES, $3, $5); } | DATATYPE '(' Expression ')' { $$=rasqal_new_1op_expression(RASQAL_EXPR_DATATYPE, $3); } | BOUND '(' Var ')' { rasqal_literal *l=rasqal_new_variable_literal($3); rasqal_expression *e=rasqal_new_literal_expression(l); $$=rasqal_new_1op_expression(RASQAL_EXPR_BOUND, e); } | ISURI '(' Expression ')' { $$=rasqal_new_1op_expression(RASQAL_EXPR_ISURI, $3); } | ISBLANK '(' Expression ')' { $$=rasqal_new_1op_expression(RASQAL_EXPR_ISBLANK, $3); } | ISLITERAL '(' Expression ')' { $$=rasqal_new_1op_expression(RASQAL_EXPR_ISLITERAL, $3); } | RegexExpression { $$=$1; } ; /* SPARQL Grammar: [58] RegexExpression */ RegexExpression: REGEX '(' Expression ',' Expression ')' { $$=rasqal_new_3op_expression(RASQAL_EXPR_REGEX, $3, $5, NULL); } | REGEX '(' Expression ',' Expression ',' Expression ')' { $$=rasqal_new_3op_expression(RASQAL_EXPR_REGEX, $3, $5, $7); } ; /* SPARQL Grammar: [59] IRIrefOrFunction - not necessary in this grammar as the IRIref ambiguity is determined in lexer with the help of the IRIrefBrace token below */ /* NEW Grammar Term made from SPARQL Grammar: [64] IRIref + '(' expanded */ IRIrefBrace: URI_LITERAL_BRACE { $$=rasqal_new_uri_literal($1); } | QNAME_LITERAL_BRACE { $$=rasqal_new_simple_literal(RASQAL_LITERAL_QNAME, $1); if(rasqal_literal_expand_qname((rasqal_query*)rq, $$)) { sparql_query_error_full((rasqal_query*)rq, "QName %s cannot be expanded", $1); rasqal_free_literal($$); $$=NULL; } } ; /* SPARQL Grammar: [60] RDFLiteral - merged into GraphTerm */ /* SPARQL Grammar: [61] NumericLiteral - merged into GraphTerm */ /* SPARQL Grammar: [62] BooleanLiteral - merged into GraphTerm */ /* SPARQL Grammar: [63] String - merged into GraphTerm */ /* SPARQL Grammar: [64] IRIref */ IRIref: URI_LITERAL { $$=rasqal_new_uri_literal($1); } | QNAME_LITERAL { $$=rasqal_new_simple_literal(RASQAL_LITERAL_QNAME, $1); if(rasqal_literal_expand_qname((rasqal_query*)rq, $$)) { sparql_query_error_full((rasqal_query*)rq, "QName %s cannot be expanded", $1); rasqal_free_literal($$); $$=NULL; } } ; /* SPARQL Grammar: [65] QName - made into terminal QNAME_LITERAL */ /* SPARQL Grammar: [66] BlankNode */ BlankNode: BLANK_LITERAL { $$=rasqal_new_simple_literal(RASQAL_LITERAL_BLANK, $1); } | '[' ']' { const unsigned char *id=rasqal_query_generate_bnodeid((rasqal_query*)rq, NULL); $$=rasqal_new_simple_literal(RASQAL_LITERAL_BLANK, id); } ; /* SPARQL Grammar: [67] Q_IRI_REF onwards are all lexer items * with similar names or are inlined. */ %% /* Support functions */ /* This is declared in sparql_lexer.h but never used, so we always get * a warning unless this dummy code is here. Used once below in an error case. */ static int yy_init_globals (yyscan_t yyscanner ) { return 0; }; static int sparql_is_builtin_xsd_datatype(raptor_uri* uri) { return (raptor_uri_equals(uri, rasqal_xsd_boolean_uri) || raptor_uri_equals(uri, rasqal_xsd_string_uri) || raptor_uri_equals(uri, rasqal_xsd_double_uri) || raptor_uri_equals(uri, rasqal_xsd_float_uri) || raptor_uri_equals(uri, rasqal_xsd_decimal_uri) || raptor_uri_equals(uri, rasqal_xsd_integer_uri) || raptor_uri_equals(uri, rasqal_xsd_datetime_uri) ); } /** * rasqal_sparql_query_engine_init - Initialise the SPARQL query engine * * Return value: non 0 on failure **/ static int rasqal_sparql_query_engine_init(rasqal_query* rdf_query, const char *name) { /* rasqal_sparql_query_engine* sparql=(rasqal_sparql_query_engine*)rdf_query->context; */ rdf_query->compare_flags = RASQAL_COMPARE_XQUERY; return 0; } /** * rasqal_sparql_query_engine_terminate - Free the SPARQL query engine * * Return value: non 0 on failure **/ static void rasqal_sparql_query_engine_terminate(rasqal_query* rdf_query) { rasqal_sparql_query_engine* sparql=(rasqal_sparql_query_engine*)rdf_query->context; if(sparql->scanner_set) { sparql_lexer_lex_destroy(sparql->scanner); sparql->scanner_set=0; } } static int rasqal_sparql_query_engine_prepare(rasqal_query* rdf_query) { /* rasqal_sparql_query_engine* sparql=(rasqal_sparql_query_engine*)rdf_query->context; */ int rc; if(!rdf_query->query_string) return 1; rc=sparql_parse(rdf_query, rdf_query->query_string); if(rc) return rc; /* FIXME - should check remaining query parts */ if(rasqal_engine_sequence_has_qname(rdf_query->triples) || rasqal_engine_sequence_has_qname(rdf_query->constructs) || rasqal_engine_query_constraints_has_qname(rdf_query)) { sparql_query_error(rdf_query, "SPARQL query has unexpanded QNames"); return 1; } return rasqal_engine_prepare(rdf_query); } static int rasqal_sparql_query_engine_execute(rasqal_query* rdf_query, rasqal_query_results *results) { /* rasqal_sparql_query_engine* sparql=(rasqal_sparql_query_engine*)rdf_query->context; */ /* nothing needed here */ return 0; } static int sparql_parse(rasqal_query* rq, const unsigned char *string) { rasqal_sparql_query_engine* rqe=(rasqal_sparql_query_engine*)rq->context; raptor_locator *locator=&rq->locator; char *buf=NULL; size_t len; void *buffer; if(!string || !*string) return yy_init_globals(NULL); /* 0 but a way to use yy_init_globals */ locator->line=1; locator->column= -1; /* No column info */ locator->byte= -1; /* No bytes info */ #if RASQAL_DEBUG > 2 sparql_parser_debug=1; #endif rqe->lineno=1; sparql_lexer_lex_init(&rqe->scanner); rqe->scanner_set=1; sparql_lexer_set_extra(((rasqal_query*)rq), rqe->scanner); /* This * buffer= sparql_lexer__scan_string((const char*)string, rqe->scanner); * is replaced by the code below. * * The extra space appended to the buffer is the least-pain * workaround to the lexer crashing by reading EOF twice in * sparql_copy_regex_token; at least as far as I can diagnose. The * fix here costs little to add as the above function does * something very similar to this anyway. */ len= strlen((const char*)string); buf= (char *)RASQAL_MALLOC(cstring, len+3); strncpy(buf, (const char*)string, len); buf[len]= ' '; buf[len+1]= buf[len+2]='\0'; /* YY_END_OF_BUFFER_CHAR; */ buffer= sparql_lexer__scan_buffer(buf, len+3, rqe->scanner); sparql_parser_parse(rq); if(buf) RASQAL_FREE(cstring, buf); sparql_lexer_lex_destroy(rqe->scanner); rqe->scanner_set=0; /* Parsing failed */ if(rq->failed) return 1; return 0; } static void sparql_query_error(rasqal_query *rq, const char *msg) { rasqal_sparql_query_engine* rqe=(rasqal_sparql_query_engine*)rq->context; rq->locator.line=rqe->lineno; #ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS /* rq->locator.column=sparql_lexer_get_column(yyscanner);*/ #endif rasqal_query_error(rq, "%s", msg); } static void sparql_query_error_full(rasqal_query *rq, const char *message, ...) { va_list arguments; rasqal_sparql_query_engine* rqe=(rasqal_sparql_query_engine*)rq->context; rq->locator.line=rqe->lineno; #ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS /* rq->locator.column=sparql_lexer_get_column(yyscanner);*/ #endif va_start(arguments, message); rasqal_query_error_varargs(rq, message, arguments); va_end(arguments); } int sparql_syntax_error(rasqal_query *rq, const char *message, ...) { rasqal_sparql_query_engine *rqe=(rasqal_sparql_query_engine*)rq->context; va_list arguments; rq->locator.line=rqe->lineno; #ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS /* rp->locator.column=sparql_lexer_get_column(yyscanner);*/ #endif va_start(arguments, message); rasqal_query_error_varargs(rq, message, arguments); va_end(arguments); return (0); } int sparql_syntax_warning(rasqal_query *rq, const char *message, ...) { rasqal_sparql_query_engine *rqe=(rasqal_sparql_query_engine*)rq->context; va_list arguments; rq->locator.line=rqe->lineno; #ifdef RASQAL_SPARQL_USE_ERROR_COLUMNS /* rq->locator.column=sparql_lexer_get_column(yyscanner);*/ #endif va_start(arguments, message); rasqal_query_warning_varargs(rq, message, arguments); va_end(arguments); return (0); } static int rasqal_sparql_query_engine_iostream_write_escaped_counted_string(rasqal_query* query, raptor_iostream* iostr, const unsigned char* string, size_t len) { const char delim='"'; raptor_iostream_write_byte(iostr, delim); if(raptor_iostream_write_string_ntriples(iostr, string, len, delim)) return 1; raptor_iostream_write_byte(iostr, delim); return 0; } static void rasqal_sparql_query_engine_register_factory(rasqal_query_engine_factory *factory) { factory->context_length = sizeof(rasqal_sparql_query_engine); factory->init = rasqal_sparql_query_engine_init; factory->terminate = rasqal_sparql_query_engine_terminate; factory->prepare = rasqal_sparql_query_engine_prepare; factory->execute = rasqal_sparql_query_engine_execute; factory->iostream_write_escaped_counted_string = rasqal_sparql_query_engine_iostream_write_escaped_counted_string; } void rasqal_init_query_engine_sparql(void) { rasqal_query_engine_register_factory("sparql", "SPARQL W3C DAWG RDF Query Language", NULL, (const unsigned char*)"http://www.w3.org/TR/rdf-sparql-query/", &rasqal_sparql_query_engine_register_factory); } #ifdef STANDALONE #include #include #define SPARQL_FILE_BUF_SIZE 2048 int main(int argc, char *argv[]) { const char *program=rasqal_basename(argv[0]); char query_string[SPARQL_FILE_BUF_SIZE]; rasqal_query *query; FILE *fh; int rc; const char *filename=NULL; raptor_uri* base_uri=NULL; unsigned char *uri_string; #if RASQAL_DEBUG > 2 sparql_parser_debug=1; #endif if(argc > 1) { filename=argv[1]; fh = fopen(argv[1], "r"); if(!fh) { fprintf(stderr, "%s: Cannot open file %s - %s\n", program, filename, strerror(errno)); exit(1); } } else { filename=""; fh = stdin; } memset(query_string, 0, SPARQL_FILE_BUF_SIZE); rc=fread(query_string, SPARQL_FILE_BUF_SIZE, 1, fh); if(rc < SPARQL_FILE_BUF_SIZE) { if(ferror(fh)) { fprintf(stderr, "%s: file '%s' read failed - %s\n", program, filename, strerror(errno)); fclose(fh); return(1); } } if(argc>1) fclose(fh); rasqal_init(); query=rasqal_new_query("sparql", NULL); uri_string=raptor_uri_filename_to_uri_string(filename); base_uri=raptor_new_uri(uri_string); rc=rasqal_query_prepare(query, (const unsigned char*)query_string, base_uri); rasqal_query_print(query, DEBUG_FH); rasqal_free_query(query); raptor_free_uri(base_uri); raptor_free_memory(uri_string); rasqal_finish(); return rc; } #endif