1:- module(sparql_dcg,[
    2      select//3
    3   ,  describe//1
    4   ,  describe//2
    5   ,  ask//1
    6	]).

A simple DCG for generating a subset of SPARQL

sparql_goal ---> (sparql_goal, sparql_goal) % conjunction
               ; (sparql_goal; sparql_goal) % disjunction
               ; rdf(resource,resource,object)
               ; filter(cond)
               .

resource :< object. % any resource is an object

literal(+literal)   :: object.  % any ground literal is an object
atomic              :< literal. % any atomic can be a plain literal
lang(atom,atom)     :: literal. % literal with language
type(resource,atom) :: literal. % typed literal

object   :< expr. % any object is an expr
number   :< expr. % Prolog numerical values can also be expressions

condition ---> (cond , cond)
             ; (cond ; cond)
             ; \+ cond
             ; expr == expr
             ; expr \= expr
             ; expr >= expr
             ; expr =< expr
             ; expr < expr
             ; expr > expr
             ; between(expr,expr,expr)
             ; in(object,list(object))
             ; regex(pattern,value)
             ; bound(object)
             ; blank(resource)
             ; uri(object)
             ; literal(object)
             .

expr ---> expr + expr
        ; expr - expr
        ; expr * expr
        ; expr / expr
        ; +expr
        ; -expr
        ; str(expr)
        ; lang(expr)
        ; datatype(expr)
        .

var ---> '$VAR'(integer)
       ; '@'        % anonymous blank node
       ; '@'(atom)  % nonymous blank node
       .

var :< resource
var :< literal

Samer Abdallah, Dept. of Computer Science, UCL (2014) /

   69:- use_module(library(semweb/rdf_db), [rdf_global_object/2, rdf_global_id/2]).   70:- use_module(library(dcg_core)).   71:- use_module(library(dcg_codes)).   72
   73:- set_prolog_flag(double_quotes, codes).
 select(+Vars:list(expr), +Goal:sparql_goal, +Options:list(option))// is det
Any variables in the query must be represented by '$VAR'/1 terms as generated by numbervars/3.
   80select(Vars,Goal,Options) -->
   81   "SELECT ", 
   82   if_option(distinct(Distinct), if(Distinct=true, " DISTINCT "),Options,O1),
   83   seqmap_with_sep(" ",expr,Vars), " ",
   84   where(Goal),
   85   if_option(order_by(OB), (" ORDER BY ", expr(OB)), O1,O2),
   86   if_option(limit(Limit), (" LIMIT ", at(Limit)), O2,O3),
   87   if_option(offset(Offs), (" OFFSET ", at(Offs)), O3,O4),
   88   {check_remaining_options(O4)}.
   89
   90check_remaining_options([]) :- !.
   91check_remaining_options(Opts) :- throw(unrecognised_options(Opts)).
   92
   93if_option(Opt,Phrase,O1,O2) -->
   94   ( {select_option(Opt,O1,O2)} -> call_dcg(Phrase); {O2=O1}).
 ask(+Goal:sparql_goal)// is det
Format an ASK query.
   99ask(Goal) --> "ASK ", brace(goal(Goal)).
 describe(+Resource:resource)// is det
 describe(+Resource:resource, +Goal:sparql_goal)// is det
  104describe(R) --> "DESCRIBE ", resource(R).
  105describe(RS,Goal) --> 
  106   "DESCRIBE ", 
  107   seqmap_with_sep(" ",resource,RS),
  108   where(Goal).
 where(+Goal:sparql_goal)// is det
  111where(Goal) --> "WHERE ", brace(goal(Goal)).
 goal(+Goal)// is det
  114goal(G1;G2)   --> brace(goal(G1)), " UNION ", brace(goal(G2)).
  115goal(\+G)     --> "FILTER NOT EXISTS ", brace(goal(G)). %NB consider MINUS { ... } also
  116goal((G1,G2)) --> goal(G1), " . ", goal(G2).
  117goal(conj(GS)) --> seqmap_with_sep(" , ",goal,GS).
  118
  119goal(rdf(S,P,O)) -->
  120   { rdf_global_object(O,OO) },
  121   resource(S), " ",
  122   resource(P), " ",
  123   object(OO).
  124
  125goal(filter(Cond)) --> "FILTER ", cond(Cond).
  126
  127:- op(1150,fx,p).  128p(X) --> paren(X).
  129
  130cond(\+C)   --> p  "! ", cond(C).
  131cond((X,Y)) --> p cond(X), " && ", cond(Y).
  132cond((X;Y)) --> p cond(X), " || ", cond(Y).
  133cond(X==Y)  --> p expr(X), " = ", expr(Y).
  134cond(X\=Y)  --> p expr(X), " != ", expr(Y).
  135cond(X=<Y)  --> p expr(X), " <= ", expr(Y).
  136cond(X>=Y)  --> p expr(X), " >= ", expr(Y).
  137cond(X>Y)   --> p expr(X), " > ", expr(Y).
  138cond(X<Y)   --> p expr(X), " < ", expr(Y).
  139cond(between(L,U,X)) --> cond((L=<X,X=<U)).
  140cond(in(X,Ys))     --> p expr(X), " in ", (p seqmap_with_sep(", ",expr,Ys)).
  141cond(regex(P,V))   --> "regex(", object(V), ",", quote(at(P)), ")".
  142cond(regex(P,V,F)) --> "regex(", object(V), ",", quote(at(P)),  ",", quote(at(F)), ")".
  143cond(bound(V))     --> "bound(", object(V), ")".
  144cond(uri(V))       --> "isURI(", object(V), ")".
  145cond(blank(V))     --> "isBLANK(", object(V), ")".
  146cond(literal(V))   --> "isLITERAL(", object(V), ")".
  147
  148expr(str(V))       --> "STR(", object(V), ")".
  149expr(lang(V))      --> "LANG(", object(V), ")".
  150expr(count(X))     --> "COUNT(", expr(X), ")".
  151expr(datatype(V))  --> "DATATYPE(", object(V), ")".
  152
  153expr(+X) -->  p "+ ", expr(X), ")".
  154expr(-X) -->  p "- ", expr(X), ")".
  155expr(X+Y) --> p expr(X), " + ", expr(Y).
  156expr(X-Y) --> p expr(X), " + ", expr(Y).
  157expr(X*Y) --> p expr(X), " * ", expr(Y).
  158expr(X/Y) --> p expr(X), " / ", expr(Y).
  159expr(X) --> {number(X)}, at(X).
  160expr(X) --> object(X).
  161
  162resource(R) --> variable(R).
  163resource(R) --> {rdf_global_id(R,RR)}, uri(RR).
  164
  165object(literal(Lit)) --> literal(Lit).
  166object(Resource) --> resource(Resource).
  167
  168literal(lang(Lang,Val)) --> quote(at(Val)), "@", at(Lang).
  169literal(type(Type,Val)) --> quote(wr(Val)), "^^", resource(Type).
  170literal(Lit) --> {atomic(Lit)}, quote(at(Lit)).
  171
  172uri(U) --> {atom(U)}, "<", at(U), ">".
  173quote(P) --> "\"", escape_with(0'",0'\\,P), "\"".
  174variable(V)  --> {var_number(V,N)}, "?v", at(N).
  175variable(@V) --> "_:", {atomic(V) -> N=V; var_number(V,N)}, at(N).
  176variable(@)  --> "[]"