You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2012/06/22 22:33:53 UTC

svn commit: r1353021 [1/2] - in /jena/trunk/jena-arq: ./ Grammar/ src/main/java/com/hp/hpl/jena/sparql/expr/ src/main/java/com/hp/hpl/jena/sparql/lang/arq/ src/test/java/com/hp/hpl/jena/sparql/expr/

Author: rvesse
Date: Fri Jun 22 20:33:52 2012
New Revision: 1353021

URL: http://svn.apache.org/viewvc?rev=1353021&view=rev
Log:
Experimental implementation of a CALL() built-in in the ARQ query language for dynamic function invocation with some rudimentary unit tests for this (JENA-270)

Modified:
    jena/trunk/jena-arq/Grammar/arq.jj
    jena/trunk/jena-arq/Grammar/master.jj
    jena/trunk/jena-arq/ReleaseNotes.txt
    jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/E_Call.java
    jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/lang/arq/ARQParser.java
    jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java

Modified: jena/trunk/jena-arq/Grammar/arq.jj
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/Grammar/arq.jj?rev=1353021&r1=1353020&r2=1353021&view=diff
==============================================================================
--- jena/trunk/jena-arq/Grammar/arq.jj (original)
+++ jena/trunk/jena-arq/Grammar/arq.jj Fri Jun 22 20:33:52 2012
@@ -1,3 +1,5 @@
+
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,23 +18,26 @@
  * limitations under the License.
  */
 
-// ARQ/SPARQL 1.1 Grammar - native syntax for the query engine
+// 1/SPARQL 1.1 Grammar - native syntax for the query engine
 // UPDATE : SPARQL 1.1. Update
 // ARQ_UPDATE : extensions to SPARQL 1.1 Update to cover SPARQL/Update (W3C Submission)
 options
 {
       // \ u processed in the input stream
       // SPARQL 1.0
-    JAVA_UNICODE_ESCAPE = true ;
-    UNICODE_INPUT = false ;
+    JAVA_UNICODE_ESCAPE   = true ;
+    UNICODE_INPUT         = false ;
+
 //       // \ u processed after parsing.
 //       // strings, prefix names, IRIs
 //       JAVA_UNICODE_ESCAPE   = false ;
 //       UNICODE_INPUT         = true ;
-  STATIC = false ;
+
+  STATIC                = false ;
 //  DEBUG_PARSER          = true ;
 //  DEBUG_TOKEN_MANAGER   = true ;
 }
+
 PARSER_BEGIN(ARQParser)
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -51,7 +56,9 @@ PARSER_BEGIN(ARQParser)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.hp.hpl.jena.sparql.lang.arq ;
+
 import com.hp.hpl.jena.graph.* ;
 import com.hp.hpl.jena.query.* ;
 import com.hp.hpl.jena.sparql.core.Var ;
@@ -61,17 +68,20 @@ import com.hp.hpl.jena.sparql.path.* ;
 import com.hp.hpl.jena.sparql.expr.aggregate.* ;
 import com.hp.hpl.jena.update.* ;
 import com.hp.hpl.jena.sparql.modify.request.* ;
+
 public class ARQParser extends ARQParserBase
 {
     boolean allowAggregatesInExpressions = false ;
 }
 PARSER_END(ARQParser)
+
 // // Common top for single entry point.
 // void Top(): {}
 // {
 //     ( Query() | Update() )
 //     <EOF>
 // }
+
 // Query only entry point
 void QueryUnit(): { }
 {
@@ -79,16 +89,19 @@ void QueryUnit(): { }
   Query() <EOF>
   { finishQuery() ; }
 }
+
 void Query() : { }
-{
+{    
   Prologue()
-  ( SelectQuery() | ConstructQuery() | DescribeQuery() | AskQuery()
-// #ifdef ARQ
+  ( SelectQuery() | ConstructQuery() | DescribeQuery() | AskQuery() 
+// #ifdef 1
 //   | JsonTemplateQuery()
 // #endif
   )
   ValuesClause()
 }
+
+
 void UpdateUnit() : {}
 {
   { startUpdateRequest() ; }
@@ -96,67 +109,84 @@ void UpdateUnit() : {}
   <EOF>
   { finishUpdateRequest() ; }
 }
+
+
+
 void Prologue() : {}
 {
   ( BaseDecl() | PrefixDecl() )*
 }
+
 void BaseDecl() : { String iri ; }
 {
   <BASE> iri = IRIREF()
   { getPrologue().setBaseURI(iri) ; }
 }
+
 void PrefixDecl() : { Token t ; String iri ; }
 {
     <PREFIX> t = <PNAME_NS> iri = IRIREF()
       { String s = fixupPrefix(t.image, t.beginLine, t.beginColumn) ;
         getPrologue().setPrefix(s, iri) ; }
 }
+
 // ---- Query type clauses
+
 void SelectQuery() : { }
-{
+{  
   SelectClause()
   ( DatasetClause() )*
   WhereClause()
   SolutionModifier()
 }
+
 void SubSelect() :{ }
-{
+{  
   SelectClause()
   WhereClause()
   SolutionModifier()
   ValuesClause()
-}
-void SelectClause() : { Var v ; Expr expr ; Node n ; }
+} 
+
+void SelectClause() : {  Var v ; Expr expr ; Node n ; }
 {
   <SELECT>
     { getQuery().setQuerySelectType() ; }
-  ( <DISTINCT> { getQuery().setDistinct(true);}
-  | <REDUCED> { getQuery().setReduced(true); }
-  )?
+  ( <DISTINCT> { getQuery().setDistinct(true);} 
+  | <REDUCED>  { getQuery().setReduced(true); }
+  )? 
+
   { allowAggregatesInExpressions = true ; }
   (
     (
-      v = Var() { getQuery().addResultVar(v) ; }
-    |
+      v = Var()                     { getQuery().addResultVar(v) ; }
+    | 
+
       // Expressions without ()
       ( LOOKAHEAD(2)
-        expr = BuiltInCall() { getQuery().addResultVar((Var)null, expr) ; }
-      | expr = FunctionCall() { getQuery().addResultVar((Var)null, expr) ; }
-      | n = RDFLiteral() { getQuery().addResultVar((Var)null, NodeValue.makeNode(n)) ; }
-      | n = NumericLiteral() { getQuery().addResultVar((Var)null, NodeValue.makeNode(n)) ; }
-      | n = BooleanLiteral() { getQuery().addResultVar((Var)null, NodeValue.makeNode(n)) ; }
+        expr = BuiltInCall()        { getQuery().addResultVar((Var)null, expr) ; }
+      | expr = FunctionCall()       { getQuery().addResultVar((Var)null, expr) ; }
+      | n = RDFLiteral()            { getQuery().addResultVar((Var)null, NodeValue.makeNode(n)) ; }
+      | n = NumericLiteral()        { getQuery().addResultVar((Var)null, NodeValue.makeNode(n)) ; }
+      | n = BooleanLiteral()        { getQuery().addResultVar((Var)null, NodeValue.makeNode(n)) ; }
       )
       // @@ PROBLEMS: expr = FunctionCall()
       // <uri>(?x)
       // looks like a function call and also a "<uri> ( ?v )"
       //| expr = FunctionCall()  { getQuery().addResultVar((Var)null, expr) ; }
     |
+
         // Expressions with ()
       (
         { v = null ; }
         <LPAREN>
-        expr = Expression()
+        expr = Expression() 
+
+
+
+
         ( <AS> v = Var() ) ?
+
         <RPAREN>
         { getQuery().addResultVar(v, expr) ; }
       )
@@ -167,10 +197,15 @@ void SelectClause() : { Var v ; Expr exp
   )
   { allowAggregatesInExpressions = false ; }
 }
-void ConstructQuery() : { Template t ;
+
+
+
+
+
+void ConstructQuery() : { Template t ; 
                           TripleCollectorBGP acc = new TripleCollectorBGP() ; }
 {
-// #ifndef ARQ
+// #ifndef 1
 //   <CONSTRUCT>
 //      { getQuery().setQueryConstructType() ; }
 //   t = ConstructTemplate() 
@@ -179,11 +214,12 @@ void ConstructQuery() : { Template t ;
 //   WhereClause()
 //   SolutionModifier()
 // #else
+
  <CONSTRUCT>
    { getQuery().setQueryConstructType() ; }
  (
     // Full form.
-    t = ConstructTemplate()
+    t = ConstructTemplate() 
       { getQuery().setConstructTemplate(t) ; }
     ( DatasetClause() )*
     WhereClause()
@@ -193,11 +229,11 @@ void ConstructQuery() : { Template t ;
     ( DatasetClause() )*
     <WHERE>
     // Should have been "ConstructTemplate()"
-    <LBRACE>
+    <LBRACE>  
     (TriplesTemplate(acc))?
     <RBRACE>
     SolutionModifier()
-    {
+    { 
       t = new Template(acc.getBGP()) ;
       getQuery().setConstructTemplate(t) ;
       // Create a query in the same shape as the query created by writing out in full.
@@ -209,6 +245,7 @@ void ConstructQuery() : { Template t ;
  )
 //#endif
 }
+
 void DescribeQuery() : { Node n ; }
 {
   <DESCRIBE>
@@ -224,6 +261,7 @@ void DescribeQuery() : { Node n ; }
   ( WhereClause() )?
   SolutionModifier()
 }
+
 void AskQuery() : {}
 {
   <ASK> { getQuery().setQueryAskType() ; }
@@ -231,137 +269,160 @@ void AskQuery() : {}
   WhereClause()
   SolutionModifier()
 }
+
 // ----
+
 void DatasetClause() : {}
 {
   <FROM>
   ( DefaultGraphClause() | NamedGraphClause() )
 }
+
 void DefaultGraphClause() : { String iri ; }
 {
-  iri = SourceSelector()
+  iri = SourceSelector() 
   {
     // This checks for duplicates
     getQuery().addGraphURI(iri) ;
   }
 }
+
 void NamedGraphClause() : { String iri ; }
 {
   <NAMED>
   iri = SourceSelector()
-  {
+  { 
     // This checks for duplicates
     getQuery().addNamedGraphURI(iri) ;
   }
 }
+
 String SourceSelector() : { String iri ; }
 {
   iri = iri() { return iri ; }
 }
+
+
 void WhereClause() : { Element el ; }
 {
    (<WHERE>)? el = GroupGraphPattern() { getQuery().setQueryPattern(el) ; }
 }
+
 void SolutionModifier() : { }
 {
   ( GroupClause() )?
   ( HavingClause() )?
   ( OrderClause() )?
-  ( LimitOffsetClauses() )?
+  ( LimitOffsetClauses() )? 
 }
+
 void GroupClause() : { }
 {
   <GROUP> <BY> ( GroupCondition() )+
 }
+
 void GroupCondition() : { Var v = null ; Expr expr = null ; }
 {
-  ( expr = BuiltInCall() { getQuery().addGroupBy((Var)null, expr) ; }
-  | expr = FunctionCall() { getQuery().addGroupBy((Var)null, expr) ; }
+  ( expr = BuiltInCall()   { getQuery().addGroupBy((Var)null, expr) ; }
+  | expr = FunctionCall()  { getQuery().addGroupBy((Var)null, expr) ; }
   |
     <LPAREN>
-      expr = Expression()
-    ( <AS> v = Var() )?
+      expr = Expression() 
+    ( <AS>  v = Var() )?
     <RPAREN>
     { getQuery().addGroupBy(v ,expr) ; }
   | v = Var()
     { getQuery().addGroupBy(v) ; }
   )
 }
+
 void HavingClause() : { }
 {
     { allowAggregatesInExpressions = true ; }
     <HAVING> (HavingCondition())+
     { allowAggregatesInExpressions = false ; }
 }
+
 void HavingCondition() : { Expr c ; }
 {
   c = Constraint()
   { getQuery().addHavingCondition(c) ; }
 }
+
 void OrderClause() : { }
 {
   { allowAggregatesInExpressions = true ; }
   <ORDER> <BY> ( OrderCondition() )+
   { allowAggregatesInExpressions = false ; }
 }
+
 void OrderCondition() :
 { int direction = 0 ; Expr expr = null ; Node v = null ; }
 {
   { direction = Query.ORDER_DEFAULT ; }
   (
     ( // These are for clarity in the HTML
-      ( <ASC> { direction = Query.ORDER_ASCENDING ; }
-      | <DESC> { direction = Query.ORDER_DESCENDING ; } )
-      expr = BrackettedExpression()
+      ( <ASC>  { direction = Query.ORDER_ASCENDING ; }
+      | <DESC> { direction = Query.ORDER_DESCENDING ; } ) 
+      expr = BrackettedExpression() 
     )
   |
     ( expr = Constraint()
     | v = Var() //{ expr = asExpr(v) ; } 
-    )
+    ) 
   )
   { if ( v == null )
           getQuery().addOrderBy(expr, direction) ;
       else
           getQuery().addOrderBy(v, direction) ; }
 }
+
 void LimitOffsetClauses() : { }
 {
   // SPARQL does not care about the order here.
   // SQL (where implemented) does (it's LIMIT then OFFSET generally)
   // But that is counter intuitive as it's applied the other way round
   (
-    LimitClause() (OffsetClause())?
+    LimitClause() (OffsetClause())? 
   |
-    OffsetClause() (LimitClause())?
+    OffsetClause() (LimitClause())? 
   )
 }
+
 void LimitClause() : { Token t ; }
 {
   <LIMIT> t = <INTEGER>
     { getQuery().setLimit(integerValue(t.image)) ; }
 }
+
 void OffsetClause() : { Token t ; }
 {
   <OFFSET> t = <INTEGER>
     { getQuery().setOffset(integerValue(t.image)) ; }
 }
+
 void ValuesClause() : { Token t ; }
 {
   (
-    t = <VALUES>
+    t = <VALUES>  
     { startValuesClause(t.beginLine, t.beginColumn) ; }
     DataBlock()
     { finishValuesClause(t.beginLine, t.beginColumn) ; }
   )?
 }
+
+
 // SPARQL Update + transitional extensions for SPARQL/Update (the W3C submission)
 // Update only entry point
+
+
 // Optional SEMICOLON
 void Update() : { }
 {
    Prologue()
-   ( Update1() (<SEMICOLON>)* Update() )?
+   ( Update1() (<SEMICOLON>)*  Update() )?
 }
+
 void Update1() : { Update up ; }
 {
   { startUpdateOperation() ; }
@@ -382,83 +443,96 @@ void Update1() : { Update up ; }
     emitUpdate(up) ;
     finishUpdateOperation() ;
   }
+
 }
+
 Update Load() : { String url ; Node dest = null ; boolean silent = false ; }
 {
     // Should be +?
     //    <LOAD> ( iri() )+
-    <LOAD> (<SILENT> { silent = true ; })? url = iri()
+    <LOAD>  (<SILENT> { silent = true ; })? url = iri()
     { String iri ; }
     (<INTO> (<GRAPH>)? iri = iri() { dest = createNode(iri) ; })?
     { return new UpdateLoad(url, dest, silent) ; }
 }
+
 Update Clear() : { boolean silent = false ; Target target ; }
 {
    <CLEAR> (<SILENT> { silent = true ; })? target = GraphRefAll()
    { return new UpdateClear(target, silent) ; }
 }
+
 Update Drop() : { boolean silent = false ; Target target ; }
 {
    <DROP> (<SILENT> { silent = true ; })? target = GraphRefAll()
    { return new UpdateDrop(target, silent) ; }
 }
+
 Update Create() : { Node iri ; boolean silent = false ; }
 {
    <CREATE> (<SILENT> { silent=true ; } )? iri = GraphRef()
-   { return new UpdateCreate(iri, silent) ; }
+   { return new UpdateCreate(iri, silent) ; } 
 }
+
 Update Add() : { Target src ; Target dest ; boolean silent = false ; }
 {
-  <ADD> (<SILENT> { silent=true ; } )? src = GraphOrDefault() <TO> dest = GraphOrDefault()
+  <ADD>  (<SILENT> { silent=true ; } )? src = GraphOrDefault() <TO> dest = GraphOrDefault()
   { return new UpdateAdd(src, dest, silent) ; }
 }
-Update Move() : { Target src ; Target dest ; boolean silent = false ; }
+
+Update Move() : { Target src ; Target dest ; boolean silent = false ; } 
 {
-  <MOVE> (<SILENT> { silent=true ; } )? src = GraphOrDefault() <TO> dest = GraphOrDefault()
+  <MOVE>  (<SILENT> { silent=true ; } )? src = GraphOrDefault() <TO> dest = GraphOrDefault()
   { return new UpdateMove(src, dest, silent) ; }
 }
+
 Update Copy() : { Target src ; Target dest ; boolean silent = false ; }
 {
-  <COPY> (<SILENT> { silent=true ; } )? src = GraphOrDefault() <TO> dest = GraphOrDefault()
+  <COPY>  (<SILENT> { silent=true ; } )? src = GraphOrDefault() <TO> dest = GraphOrDefault()
   { return new UpdateCopy(src, dest, silent) ; }
 }
-// #ifdef ARQ
+
+// #ifdef 1
 // void Meta() : { QuadDataAcc qd = new QuadDataAcc() ; }
 // {
 //    <META> 
 //    QuadData(qd)
 // }
 // #endif
+
 Update InsertData() : { QuadDataAcc qd = new QuadDataAcc() ; Token t ; }
 {
-  t = <INSERT_DATA>
+  t =  <INSERT_DATA>
   { startDataInsert(qd, t.beginLine, t.beginColumn) ; }
    OptionalIntoTarget(qd)
    QuadPattern(qd)
   {
     finishDataInsert(qd, t.beginLine, t.beginColumn) ;
-    return new UpdateDataInsert(qd) ;
+    return new UpdateDataInsert(qd) ; 
   }
 }
+
 Update DeleteData() : { QuadDataAcc qd = new QuadDataAcc() ; Token t ; }
 {
   t = <DELETE_DATA>
   { startDataDelete(qd, t.beginLine, t.beginColumn) ; }
   OptionalFromTarget(qd)
   QuadData(qd)
-  {
+  { 
     finishDataDelete(qd, t.beginLine, t.beginColumn) ;
     return new UpdateDataDelete(qd) ;
   }
 }
-Update DeleteWhere() : { QuadAcc qp = new QuadAcc() ; Token t ; }
+
+Update DeleteWhere() : { QuadAcc qp = new QuadAcc() ;  Token t ; }
 {
-  t = <DELETE_WHERE>
+  t = <DELETE_WHERE> 
   { startDeleteTemplate(qp, t.beginLine, t.beginColumn) ; }
   QuadPattern(qp)
   { finishDeleteTemplate(qp, t.beginLine, t.beginColumn) ; }
   { return new UpdateDeleteWhere(qp) ; }
 }
+
 Update Modify() : { Element el ; String iri = null ;
                     UpdateModify up = new UpdateModify() ; }
 {
@@ -468,9 +542,10 @@ Update Modify() : { Element el ; String 
   )
   (UsingClause(up))*
   <WHERE>
-  el = GroupGraphPattern() { up.setElement(el) ; }
+  el = GroupGraphPattern() { up.setElement(el) ; }    
   { return up ; }
 }
+
 Update ModifyOld() :
        { UpdateModify up = new UpdateModify() ; String iri ; Template template ; Element el ; }
 {
@@ -479,10 +554,11 @@ Update ModifyOld() :
     (DeleteClause(up))?
     (InsertClause(up))?
     <WHERE>
-    el = GroupGraphPattern() { up.setElement(el) ; }
+    el = GroupGraphPattern() { up.setElement(el) ; }    
     { return up ; }
 }
-void DeleteClause(UpdateModify up) : { QuadAcc qp = up.getDeleteAcc() ; Token t ;}
+
+void DeleteClause(UpdateModify up) : { QuadAcc qp = up.getDeleteAcc() ;  Token t ;}
 {
    t = <DELETE>
    { startDeleteTemplate(qp, t.beginLine, t.beginColumn) ; }
@@ -491,6 +567,7 @@ void DeleteClause(UpdateModify up) : { Q
    { finishDeleteTemplate(qp, t.beginLine, t.beginColumn) ; }
    { up.setHasDeleteClause(true) ; }
 }
+
 void InsertClause(UpdateModify up) : { QuadAcc qp = up.getInsertAcc() ; Token t ; }
 {
    t = <INSERT>
@@ -500,59 +577,67 @@ void InsertClause(UpdateModify up) : { Q
    { finishInsertTemplate(qp, t.beginLine, t.beginColumn) ; }
    { up.setHasInsertClause(true) ; }
 }
+
 void OptionalIntoTarget(QuadAcc qp) : { String iri ; }
 {
-  ( (<INTO>)?
+  ( (<INTO>)? 
      iri = iri()
      { Node gn = createNode(iri) ; setAccGraph(qp, gn) ; }
    )?
 }
+
 void OptionalFromTarget(QuadAcc qp) : { String iri ; }
 {
-  ( (<FROM>)?
+  ( (<FROM>)? 
      iri = iri()
      { Node gn = createNode(iri) ; setAccGraph(qp, gn) ; }
    )?
 }
+
 void UsingClause(UpdateWithUsing update) : { String iri ; Node n ; }
 {
-  <USING>
-  ( iri = iri()
+  <USING> 
+  ( iri = iri() 
     { n = createNode(iri) ; update.addUsing(n) ; }
   | <NAMED> iri = iri()
     { n = createNode(iri) ; update.addUsingNamed(n) ; }
   )
 }
+
 Target GraphOrDefault() : { String iri ; }
 {
   ( <DFT> { return Target.DEFAULT ; }
-  | (<GRAPH>)?
+  |  (<GRAPH>)? 
      iri = iri()
-     { return Target.create(createNode(iri)) ; }
+     {  return Target.create(createNode(iri)) ; }
   )
 }
+
 Node GraphRef() : { String iri ; }
 {
     <GRAPH> iri = iri()
     { return createNode(iri) ; }
 }
+
 Target GraphRefAll() : { Node iri ; }
 {
-   ( iri = GraphRef()
+   ( iri = GraphRef() 
      { return Target.create(iri) ; }
-   | <DFT> { return Target.DEFAULT ; }
-   | <NAMED> { return Target.NAMED ; }
-   | <ALL> { return Target.ALL ; }
+   | <DFT>    { return Target.DEFAULT ; }
+   | <NAMED>  { return Target.NAMED ; } 
+   | <ALL>    { return Target.ALL ; } 
    )
    ?
    { return Target.DEFAULT ; }
 }
+
 void QuadPattern(QuadAcc acc) : { }
 {
     <LBRACE>
     Quads(acc)
     <RBRACE>
 }
+
 //Ground data : As QuadPattern but don't allow variables.
 void QuadData(QuadDataAcc acc) : { }
 {
@@ -560,6 +645,7 @@ void QuadData(QuadDataAcc acc) : { }
     Quads(acc)
     <RBRACE>
 }
+
 void Quads(QuadAcc acc) : { }
 {
    (TriplesTemplate(acc))?
@@ -569,30 +655,36 @@ void Quads(QuadAcc acc) : { }
      (TriplesTemplate(acc))?
    )*
 }
+
 void QuadsNotTriples(QuadAcc acc) : {Node gn ; Node prev = acc.getGraph() ; }
 {
     <GRAPH> gn = VarOrIri()
     { setAccGraph(acc, gn) ; }
-    <LBRACE>
+    <LBRACE> 
     (TriplesTemplate(acc))?
     <RBRACE>
     { setAccGraph(acc, prev) ; }
+    
 }
+
 void TriplesTemplate(TripleCollector acc) : { }
-{ // same as ConstructTriples
+{    // same as ConstructTriples
     // Rewrite for no recursion - grammar is not LL(1)
     TriplesSameSubject(acc)
     (LOOKAHEAD(2) (<DOT>) TriplesSameSubject(acc))*
     (<DOT>)?
 }
+
+
 // ---- General Graph Pattern 
+
 Element GroupGraphPattern() : { Element el = null ; Token t ; }
 {
   t = <LBRACE>
-  (
+  ( 
     { startSubSelect(t.beginLine, t.beginColumn) ; }
     SubSelect()
-    {
+    { 
       Query q = endSubSelect(t.beginLine, t.beginColumn) ;
       el = new ElementSubQuery(q) ;
     }
@@ -601,6 +693,7 @@ Element GroupGraphPattern() : { Element 
   <RBRACE>
     { return el ; }
 }
+
 Element GroupGraphPatternSub() : { Element el = null ; }
 {
       { ElementGroup elg = new ElementGroup() ; }
@@ -612,22 +705,25 @@ Element GroupGraphPatternSub() : { Eleme
     { startTriplesBlock() ; }
     el = TriplesBlock(null)
     { endTriplesBlock() ;
-      elg.addElement(el) ; }
+      elg.addElement(el) ; } 
   )?
   (
-    el = GraphPatternNotTriples()
+    el = GraphPatternNotTriples() 
     { elg.addElement(el) ; }
+
     (<DOT>)?
+
     (
       { startTriplesBlock() ; }
       el = TriplesBlock(null)
       { endTriplesBlock() ;
-        elg.addElement(el) ; }
+        elg.addElement(el) ; } 
     )?
   )*
       { endGroup(elg) ; }
       { return elg ; }
 }
+
 Element TriplesBlock(ElementPathBlock acc) : { }
 {
   { if ( acc == null )
@@ -637,7 +733,9 @@ Element TriplesBlock(ElementPathBlock ac
   ( <DOT> (TriplesBlock(acc))? )?
     { return acc ; }
 }
+
 // -----
+
 Element GraphPatternNotTriples() : { Element el = null ; }
 {
  (
@@ -669,19 +767,24 @@ Element GraphPatternNotTriples() : { Ele
  )
  { return el ; }
 }
+
 // ---- Definitions of each pattern element
+
 Element OptionalGraphPattern() : { Element el ; }
 { <OPTIONAL> el = GroupGraphPattern()
     { return new ElementOptional(el) ; }
 }
+
 Element GraphGraphPattern() : { Element el ; Node n ;}
 {
   <GRAPH> n = VarOrIri() el = GroupGraphPattern()
     { return new ElementNamedGraph(n, el) ; }
 }
+
+
 Element ServiceGraphPattern() : { Element el ; Node n ; boolean silent = false ; }
 {
-  <SERVICE>
+  <SERVICE> 
   (<SILENT>
    { silent=true; }
   )?
@@ -689,7 +792,8 @@ Element ServiceGraphPattern() : { Elemen
   el = GroupGraphPattern()
     { return new ElementService(n, el, silent) ; }
 }
-Element Bind() : { Var v ; Expr expr ; }
+
+Element Bind() : {  Var v ; Expr expr ; }
 {
   <BIND>
   <LPAREN>
@@ -699,6 +803,7 @@ Element Bind() : { Var v ; Expr expr ; }
   <RPAREN>
   { return new ElementBind(v, expr) ; }
 }
+
 Element InlineData() : { ElementData el ; Token t ; }
 {
   t = <VALUES>
@@ -708,24 +813,27 @@ Element InlineData() : { ElementData el 
   { finishInlineData(t.beginLine, t.beginColumn) ;
     return el ; }
 }
+
 void DataBlock() : { }
 {
-  ( InlineDataOneVar() | InlineDataFull() )
+  ( InlineDataOneVar() |  InlineDataFull() )
 }
+
 void InlineDataOneVar() : { Var v ; Node n ; Token t ; }
 {
   v = Var()
   { emitDataBlockVariable(v) ; }
   t = <LBRACE>
-  (
-    n = DataBlockValue()
+  ( 
+    n = DataBlockValue() 
     { startDataBlockValueRow(-1, -1) ;
       emitDataBlockValue(n, -1, -1) ;
       finishDataBlockValueRow(-1, -1) ;
     }
   )*
   t = <RBRACE>
-}
+}  
+  
 void InlineDataFull() : { Var v ; Node n ; Token t ; }
 {
   (
@@ -737,12 +845,12 @@ void InlineDataFull() : { Var v ; Node n
   )
   t = <LBRACE>
   (
-    t = <LPAREN>
+    t = <LPAREN> 
     { startDataBlockValueRow(t.beginLine, t.beginColumn) ; }
-    (n = DataBlockValue()
+    (n = DataBlockValue() 
         { emitDataBlockValue(n, t.beginLine, t.beginColumn) ; }
     ) *
-    t = <RPAREN>
+    t = <RPAREN> 
       { finishDataBlockValueRow(t.beginLine, t.beginColumn) ; }
   |
     t = <NIL>
@@ -750,51 +858,63 @@ void InlineDataFull() : { Var v ; Node n
       { finishDataBlockValueRow(t.beginLine, t.beginColumn) ; }
    )*
   t = <RBRACE>
-}
+}  
+
 Node DataBlockValue() : { Node n ; String iri ; }
 {
-  iri = iri() { return createNode(iri) ; }
-| n = RDFLiteral() { return n ; }
-| n = NumericLiteral() { return n ; }
-| n = BooleanLiteral() { return n ; }
-| <UNDEF> { return null ; }
+  iri = iri()           { return createNode(iri) ; }
+| n = RDFLiteral()      { return n ; }
+| n = NumericLiteral()  { return n ; }
+| n = BooleanLiteral()  { return n ; }
+| <UNDEF>               { return null ; }
 }
+
+
 Element Assignment() : { Var v ; Expr expr ; }
 {
-  <LET>
+  <LET>  
   <LPAREN>
   v = Var()
-  <ASSIGN>
+  <ASSIGN> 
   expr = Expression()
   <RPAREN>
     { return new ElementAssign(v, expr) ; }
 }
+
+
 Element ExistsElt() : { Element el ; }
 {
     <EXISTS>
     el = GroupGraphPattern()
     { return new ElementExists(el) ; }
 }
+
 Element NotExistsElt() : { Element el ; }
 {
     <NOT> <EXISTS>
     el = GroupGraphPattern()
     { return new ElementNotExists(el) ; }
 }
+
 Element MinusGraphPattern() : { Element el ; }
 {
     <MINUS_P>
     el = GroupGraphPattern()
     { return new ElementMinus(el) ; }
 }
+
 // Element UnionGraphPattern() : { Element el ; }
 // {
 //     <UNION>
 //     el = GroupGraphPattern()
 //     { return new ElementUnion(el) ; }
 // }
+
+
 // SPARQL 1.0: {pattern} UNION {pattern} UNION {pattern} ... :: 
 // SPARQL 1.1 may introduce: { pattern UNION pattern UNION ... }
+
+
 // G (union G)* can be a single group pattern
 // or a group pattern as part of an union.
 Element GroupOrUnionGraphPattern() :
@@ -809,32 +929,37 @@ Element GroupOrUnionGraphPattern() :
       }
     }
   el = GroupGraphPattern()
-    { el2.addElement(el) ; }
+    { el2.addElement(el) ; } 
   )*
     { return (el2==null)? el : el2 ; }
 }
+
+
 Element Filter() : { Expr c ; }
 {
   <FILTER> c = Constraint()
   { return new ElementFilter(c) ; }
 }
+
 Expr Constraint() : { Expr c ; }
 {
-  ( c = BrackettedExpression()
+  ( c = BrackettedExpression() 
   | c = BuiltInCall()
   | c = FunctionCall()
   )
   { return c ; }
 }
+
 Expr FunctionCall() : { String fname ; ExprList a ; }
 {
   fname = iri()
   a = ArgList()
   { return new E_Function(fname, a) ; }
 }
+
 ExprList ArgList() : { Expr expr ; boolean distinct = false ;
                       ExprList args = new ExprList() ; Token t ; }
-{
+{ 
   (
     <NIL>
   |
@@ -846,69 +971,80 @@ ExprList ArgList() : { Expr expr ; boole
                                  t.beginLine, t.beginColumn) ;
         }
       )?
-      expr = Expression() { args.add(expr) ; }
+      expr = Expression() { args.add(expr) ; } 
       (<COMMA> expr = Expression() { args.add(expr) ; } )*
     <RPAREN>
    )
     { return args ; }
 }
+
 ExprList ExpressionList() : { Expr expr = null ; ExprList args = new ExprList() ;}
 {
   (
     <NIL>
   |
     <LPAREN>
-    expr = Expression() { args.add(expr) ; }
-      (<COMMA> expr = Expression() { args.add(expr) ; } )*
+    expr = Expression() { args.add(expr) ; } 
+      (<COMMA> expr = Expression() { args.add(expr) ; } )* 
     <RPAREN>
   )
   { return args ; }
 }
+
+
+
 // -------- Construct patterns
-Template ConstructTemplate() : { TripleCollectorBGP acc = new TripleCollectorBGP();
+
+Template ConstructTemplate() : { TripleCollectorBGP acc = new TripleCollectorBGP(); 
                                  Template t = new Template(acc.getBGP()) ; }
 {
     { setInConstructTemplate(true) ; }
-  <LBRACE>
+  <LBRACE> 
     (ConstructTriples(acc))?
   <RBRACE>
     { setInConstructTemplate(false) ;
       return t ; }
 }
+
 void ConstructTriples(TripleCollector acc) : { }
-{ // Same as TriplesTemplate, but retain for 1.0 legacy
+{    // Same as TriplesTemplate, but retain for 1.0 legacy
     // Rewrite for no recursion - grammar is not LL(1)
     TriplesSameSubject(acc)
     (LOOKAHEAD(2) (<DOT>) TriplesSameSubject(acc))*
     (<DOT>)?
 }
+
 // -------- Triple lists with property and object lists
 // -------- Without paths: entry: TriplesSameSubject
-void TriplesSameSubject(TripleCollector acc) : { Node s ; }
+
+void TriplesSameSubject(TripleCollector acc) : { Node s ; } 
 {
   s = VarOrTerm()
-  PropertyListNotEmpty(s, acc)
+  PropertyListNotEmpty(s, acc) 
 |
   // Any of the triple generating syntax elements
   s = TriplesNode(acc)
   PropertyList(s, acc)
 }
+
 void PropertyList(Node s, TripleCollector acc) : { }
 {
   ( PropertyListNotEmpty(s, acc) ) ?
 }
-void PropertyListNotEmpty(Node s, TripleCollector acc) :
+
+void PropertyListNotEmpty(Node s, TripleCollector acc) : 
     { Node p = null ; }
 {
     p = Verb()
     ObjectList(s, p, null, acc)
-  ( <SEMICOLON>
+  ( <SEMICOLON> 
     (
        p = Verb()
       ObjectList(s, p, null, acc)
-    )?
+    )? 
   )*
 }
+
 Node Verb() : { Node p ;}
 {
 // Blank nodes as predicates
@@ -916,53 +1052,63 @@ Node Verb() : { Node p ;}
   ( p = VarOrIri() | <KW_A> { p = nRDFtype ; } )
   { return p ; }
 }
-void ObjectList(Node s, Node p, Path path, TripleCollector acc): { Node o ; }
+
+void ObjectList(Node s,  Node p, Path path, TripleCollector acc): { Node o ; } 
 {
   Object(s, p, path, acc)
   ( <COMMA> Object(s, p, path, acc) )*
 }
+
 void Object(Node s, Node p, Path path, TripleCollector acc): { Node o ; }
 {
     { int mark = acc.mark() ; }
-  o = GraphNode(acc)
+  o = GraphNode(acc) 
   { insert(acc, mark, s, p, path, o) ; }
 }
+
 // -------- BGPs with paths.
 // -------- Entry point: TriplesSameSubjectPath
-void TriplesSameSubjectPath(TripleCollector acc) : { Node s ; }
+
+void TriplesSameSubjectPath(TripleCollector acc) : { Node s ; } 
 {
   s = VarOrTerm()
-  PropertyListPathNotEmpty(s, acc)
+  PropertyListPathNotEmpty(s, acc) 
 |
   // Any of the triple generating syntax elements
   s = TriplesNodePath(acc)
   PropertyListPath(s, acc)
 }
+
+
 void PropertyListPath(Node s, TripleCollector acc) : { }
 {
   ( PropertyListPathNotEmpty(s, acc) ) ?
 }
-void PropertyListPathNotEmpty(Node s, TripleCollector acc) :
+
+void PropertyListPathNotEmpty(Node s, TripleCollector acc) : 
     { Path path = null ; Node p = null ; }
 {
   ( path = VerbPath()
   | p = VerbSimple()
   )
+
   ObjectListPath(s, p, path, acc)
-  ( <SEMICOLON>
+  ( <SEMICOLON> 
     { path = null ; p = null ; }
     (
       ( path = VerbPath()
       | p = VerbSimple()
       )
       ObjectList(s, p, path, acc)
-    )?
+    )? 
   )*
 }
+
 Path VerbPath() : {Node p ; Path path ; }
 {
   path = Path() { return path ; }
 }
+
 Node VerbSimple() : { Node p ; }
 {
   // "a" now allowed in paths.
@@ -970,30 +1116,38 @@ Node VerbSimple() : { Node p ; }
   p = Var()
   { return p ; }
 }
-void ObjectListPath(Node s, Node p, Path path, TripleCollector acc): { Node o ; }
+
+void ObjectListPath(Node s,  Node p, Path path, TripleCollector acc): { Node o ; } 
 {
   ObjectPath(s, p, path, acc)
   ( <COMMA> ObjectPath(s, p, path, acc) )*
 }
+
 void ObjectPath(Node s, Node p, Path path, TripleCollector acc): { Node o ; }
 {
     { int mark = acc.mark() ; }
-  o = GraphNodePath(acc)
+  o = GraphNodePath(acc) 
   { insert(acc, mark, s, p, path, o) ; }
 }
+
+
 // End paths stuff.
+
 // -------- Paths
+
 Path PathUnit() : { Path p ; }
 {
     p = Path()
     <EOF>
     { return p ; }
 }
+
 // Weakest outermost
 Path Path() : { Path p ; }
 {
   p = PathAlternative() { return p ; }
 }
+
 Path PathAlternative() : { Path p1 , p2 ; }
 {
    p1 = PathSequence()
@@ -1003,6 +1157,7 @@ Path PathAlternative() : { Path p1 , p2 
    )*
    { return p1 ; }
 }
+
 Path PathSequence() : { Path p1 , p2 ; }
 {
     p1 = PathEltOrInverse()
@@ -1014,153 +1169,170 @@ Path PathSequence() : { Path p1 , p2 ; }
     )*
    { return p1; }
 }
+
 // Path unit element, no inverse
 Path PathElt() : { String str ; Node n ; Path p ; }
-{
-   p = PathPrimary()
+{ 
+   p = PathPrimary() 
    ( p = PathMod(p) )?
    { return p ; }
 }
+
 // Path unit element, including inverse.
 Path PathEltOrInverse() : { String str ; Node n ; Path p ; }
-{
-   ( p = PathElt()
+{ 
+   ( p = PathElt() 
    | <CARAT>
      p = PathElt()
      { p = PathFactory.pathInverse(p) ; }
    )
    { return p ; }
 }
+
 Path PathMod(Path p) : { long i1 ; long i2 ; }
 {
-   ( <QMARK> { return PathFactory.pathZeroOrOne(p) ; }
-   | <STAR> { return PathFactory.pathZeroOrMore1(p) ; }
-   | <PLUS> { return PathFactory.pathOneOrMore1(p) ; }
+   ( <QMARK>  { return PathFactory.pathZeroOrOne(p) ; }
+   | <STAR>   { return PathFactory.pathZeroOrMore1(p) ; }
+   | <PLUS>   { return PathFactory.pathOneOrMore1(p) ; }
    | <LBRACE>
          //{*}
        ( <STAR> <RBRACE> { return PathFactory.pathZeroOrMoreN(p) ; }
          // {+}
-       | <PLUS> <RBRACE> { return PathFactory.pathOneOrMoreN(p) ; }
-       | // {N} {N,M} {N,}
+       | <PLUS> <RBRACE> { return  PathFactory.pathOneOrMoreN(p) ; }
+       |  // {N} {N,M} {N,}
           i1 = Integer()
           ( <COMMA>
             ( // case {N,}
-              <RBRACE>
-              { return PathFactory.pathMod(p, i1, PathFactory.UNSET) ; }
+              <RBRACE> 
+              { return PathFactory.pathMod(p, i1, PathFactory.UNSET) ; } 
             | // case {N,M}
               i2 = Integer() <RBRACE> // case {N,M}
-              { return PathFactory.pathMod(p, i1, i2) ; }
+              { return PathFactory.pathMod(p, i1, i2) ; } 
             )
           |
-            <RBRACE> // {N}
+            <RBRACE>   // {N}
                      { return PathFactory.pathFixedLength(p, i1) ; }
           )
-       | // {,N}
+       |   // {,N}
          <COMMA>
          i2 = Integer()
          <RBRACE>
-           { return PathFactory.pathMod(p, PathFactory.UNSET, i2) ; }
+           { return PathFactory.pathMod(p, PathFactory.UNSET, i2) ; } 
        )
    )
 }
+
 Path PathPrimary() : { String str ; Path p ; Node n ; }
 {
-  (
+  ( 
     str = iri()
      { n = createNode(str) ; p = PathFactory.pathLink(n) ; }
-  | <KW_A>
+  | <KW_A> 
      { p = PathFactory.pathLink(nRDFtype) ; }
   | <BANG> p = PathNegatedPropertySet()
   | <LPAREN> p = Path() <RPAREN>
   |
-     <DISTINCT><LPAREN>
+     <DISTINCT><LPAREN> 
      p = Path()
      { p = PathFactory.pathDistinct(p) ; }
      <RPAREN>
   |
-     <SHORTEST> <LPAREN>
+     <SHORTEST> <LPAREN> 
      p = Path()
      { p = PathFactory.pathShortest(p) ; }
      <RPAREN>
   |
-     <MULTI><LPAREN>
+     <MULTI><LPAREN> 
      p = Path()
      { p = PathFactory.pathMulti(p) ; }
      <RPAREN>
   )
  { return p ; }
 }
+
 Path PathNegatedPropertySet() : { P_Path0 p ; P_NegPropSet pNegSet ; }
 {
   { pNegSet = new P_NegPropSet() ; }
+
   ( p = PathOneInPropertySet()
     { pNegSet.add(p) ; }
-  | <LPAREN>
+  | <LPAREN> 
     ( p = PathOneInPropertySet() { pNegSet.add(p) ; }
       (<VBAR> p = PathOneInPropertySet() { pNegSet.add(p) ; }) *
-    )?
+    )? 
      <RPAREN>
-  )
+  ) 
   { return pNegSet ; }
 }
+
 P_Path0 PathOneInPropertySet() : { String str ; Node n ; }
 {
-  ( str = iri() { n = createNode(str) ; return new P_Link(n) ; }
-  | <KW_A> { return new P_Link(nRDFtype) ; }
+  ( str = iri() { n = createNode(str) ; return new P_Link(n) ; } 
+  | <KW_A>         { return new P_Link(nRDFtype) ; }
   // This is the !(^:property) form.
-  | <CARAT>
-    ( str = iri() { n = createNode(str) ; return new P_ReverseLink(n) ; }
-    | <KW_A> { return new P_ReverseLink(nRDFtype) ; }
+  | <CARAT>  
+    ( str = iri() { n = createNode(str) ; return new P_ReverseLink(n) ; } 
+    | <KW_A> { return new P_ReverseLink(nRDFtype) ; } 
     )
   )
 }
+
 long Integer() : {Token t ;}
 {
-    t = <INTEGER>
+    t = <INTEGER> 
     { return integerValue(t.image) ; }
 }
+
 // -------- Triple expansions
+
 // Anything that can stand in a node slot and which is
 // a number of triples
+
 Node TriplesNode(TripleCollector acc) : { Node n ; }
 {
   n = Collection(acc) { return n ; }
  |
   n = BlankNodePropertyList(acc) { return n ; }
 }
+
 Node BlankNodePropertyList(TripleCollector acc) : { Token t ; }
 {
-  t = <LBRACKET>
+  t = <LBRACKET> 
     { Node n = createBNode( t.beginLine, t.beginColumn) ; }
   PropertyListNotEmpty(n, acc)
   <RBRACKET>
     { return n ; }
 }
+
 Node TriplesNodePath(TripleCollector acc) : { Node n ; }
 {
   n = CollectionPath(acc) { return n ; }
  |
   n = BlankNodePropertyListPath(acc) { return n ; }
 }
+
 Node BlankNodePropertyListPath(TripleCollector acc) : { Token t ; }
 {
-  t = <LBRACKET>
+  t = <LBRACKET> 
     { Node n = createBNode( t.beginLine, t.beginColumn) ; }
   PropertyListPathNotEmpty(n, acc)
   <RBRACKET>
     { return n ; }
 }
+
+
 // ------- RDF collections
-Node Collection(TripleCollector acc) :
+
+Node Collection(TripleCollector acc) : 
     { Node listHead = nRDFnil ; Node lastCell = null ; int mark ; Node n ; Token t ; }
 {
-  t = <LPAREN>
+  t = <LPAREN> 
   (
     { Node cell = createListNode( t.beginLine, t.beginColumn) ;
       if ( listHead == nRDFnil )
          listHead = cell ;
       if ( lastCell != null )
-        insert(acc, lastCell, nRDFrest, cell) ;
+        insert(acc, lastCell, nRDFrest,  cell) ;
       mark = acc.mark() ;
     }
     n = GraphNode(acc)
@@ -1172,19 +1344,20 @@ Node Collection(TripleCollector acc) :
   // Not * here - "()" is handled separately.
   <RPAREN>
    { if ( lastCell != null )
-       insert(acc, lastCell, nRDFrest, nRDFnil) ;
+       insert(acc, lastCell, nRDFrest,  nRDFnil) ;
      return listHead ; }
 }
-Node CollectionPath(TripleCollector acc) :
+
+Node CollectionPath(TripleCollector acc) : 
     { Node listHead = nRDFnil ; Node lastCell = null ; int mark ; Node n ; Token t ; }
 {
-  t = <LPAREN>
+  t = <LPAREN> 
   (
     { Node cell = createListNode( t.beginLine, t.beginColumn) ;
       if ( listHead == nRDFnil )
          listHead = cell ;
       if ( lastCell != null )
-        insert(acc, lastCell, nRDFrest, cell) ;
+        insert(acc, lastCell, nRDFrest,  cell) ;
       mark = acc.mark() ;
     }
     n = GraphNodePath(acc)
@@ -1196,62 +1369,74 @@ Node CollectionPath(TripleCollector acc)
   // Not * here - "()" is handled separately.
   <RPAREN>
    { if ( lastCell != null )
-       insert(acc, lastCell, nRDFrest, nRDFnil) ;
+       insert(acc, lastCell, nRDFrest,  nRDFnil) ;
      return listHead ; }
 }
+
 // -------- Nodes in a graph pattern or template
+
 Node GraphNode(TripleCollector acc) : { Node n ; }
 {
   n = VarOrTerm() { return n ; }
  |
   n = TriplesNode(acc) { return n ; }
 }
+
 Node GraphNodePath(TripleCollector acc) : { Node n ; }
 {
   n = VarOrTerm() { return n ; }
  |
   n = TriplesNodePath(acc) { return n ; }
 }
+
 Node VarOrTerm() : {Node n = null ; }
 {
   ( n = Var() | n = GraphTerm() )
   { return n ; }
 }
+
 // Property (if no bNodes) + DESCRIBE
 Node VarOrIri() : {Node n = null ; String iri ; }
 {
   ( n = Var() | iri = iri() { n = createNode(iri) ; } )
   { return n ; }
 }
+
 Var Var() : { Token t ;}
 {
     ( t = <VAR1> | t = <VAR2> )
     { return createVariable(t.image, t.beginLine, t.beginColumn) ; }
 }
+
 Node GraphTerm() : { Node n ; String iri ; }
 {
-  iri = iri() { return createNode(iri) ; }
-| n = RDFLiteral() { return n ; }
-| n = NumericLiteral() { return n ; }
-| n = BooleanLiteral() { return n ; }
-| n = BlankNode() { return n ; }
+  iri = iri()        { return createNode(iri) ; }
+| n = RDFLiteral()      { return n ; }
+| n = NumericLiteral()  { return n ; }
+| n = BooleanLiteral()  { return n ; }
+| n = BlankNode()       { return n ; }   
   //  <LPAREN> <RPAREN>     { return nRDFnil ; }
-| <NIL> { return nRDFnil ; }
+| <NIL>  { return nRDFnil ; }
 }
+
 // -------- Constraint syntax
+
 Expr Expression() : { Expr expr ; }
 {
   expr = ConditionalOrExpression()
   { return expr ; }
 }
+
 Expr ConditionalOrExpression() : { Expr expr1, expr2 ; }
 {
-  expr1 = ConditionalAndExpression()
+  expr1 = ConditionalAndExpression() 
   ( <SC_OR> expr2 = ConditionalAndExpression()
-    { expr1 = new E_LogicalOr(expr1, expr2) ; }
+    { expr1 = new E_LogicalOr(expr1, expr2) ; } 
   )*
     { return expr1 ; }
+    
 }
+
 Expr ConditionalAndExpression() : { Expr expr1, expr2 ;}
 {
   expr1 = ValueLogical()
@@ -1260,11 +1445,13 @@ Expr ConditionalAndExpression() : { Expr
   )*
     { return expr1 ; }
 }
+
 Expr ValueLogical() : { Expr expr ; }
 {
   expr = RelationalExpression()
     { return expr ; }
 }
+
 Expr RelationalExpression() : { Expr expr1, expr2 ; ExprList a ; }
 {
   expr1 = NumericExpression()
@@ -1288,11 +1475,13 @@ Expr RelationalExpression() : { Expr exp
   )?
     { return expr1 ; }
 }
-Expr NumericExpression () : { Expr expr ; }
+
+Expr NumericExpression ()  : { Expr expr ; }
 {
   expr = AdditiveExpression()
     { return expr ; }
 }
+
 Expr AdditiveExpression() : { Expr expr1, expr2, expr3 ; boolean addition ; Node n ; }
 {
   expr1 = MultiplicativeExpression()
@@ -1310,17 +1499,19 @@ Expr AdditiveExpression() : { Expr expr1
       }
     |
       n = NumericLiteralNegative()
-     {
+     { 
          n = stripSign(n) ;
          expr2 = asExpr(n) ;
          addition = false ;
      }
      )
+
     (
-      ( <STAR> expr3 = UnaryExpression() { expr2 = new E_Multiply(expr2, expr3) ; } )
+      ( <STAR>  expr3 = UnaryExpression() { expr2 = new E_Multiply(expr2, expr3) ; } )
     |
-      ( <SLASH> expr3 = UnaryExpression() { expr2 = new E_Divide(expr2, expr3) ; } )
+      ( <SLASH>  expr3 = UnaryExpression() { expr2 = new E_Divide(expr2, expr3) ; } )
     )*
+
     { if ( addition )
          expr1 = new E_Add(expr1, expr2) ;
       else
@@ -1329,10 +1520,11 @@ Expr AdditiveExpression() : { Expr expr1
   )*
   { return expr1 ; }
 }
+
 Expr MultiplicativeExpression() : { Expr expr1, expr2 ; }
 {
   expr1 = UnaryExpression()
-  ( <STAR> expr2 = UnaryExpression()
+  ( <STAR>  expr2 = UnaryExpression()
     { expr1 = new E_Multiply(expr1, expr2) ; }
   | <SLASH> expr2 = UnaryExpression()
     { expr1 = new E_Divide(expr1, expr2) ; }
@@ -1341,31 +1533,36 @@ Expr MultiplicativeExpression() : { Expr
   )*
     { return expr1 ; }
 }
+
 Expr UnaryExpression() : { Expr expr ; }
 {
   <BANG> expr = PrimaryExpression()
     { return new E_LogicalNot(expr) ; }
-  | <PLUS> expr = PrimaryExpression() { return new E_UnaryPlus(expr) ; }
+  | <PLUS>  expr = PrimaryExpression() { return new E_UnaryPlus(expr) ; }
   | <MINUS> expr = PrimaryExpression() { return new E_UnaryMinus(expr) ; }
   | expr = PrimaryExpression() { return expr ; }
 }
+
 Expr PrimaryExpression() : { Expr expr ; Node gn ; }
 {
   ( expr = BrackettedExpression() { return expr ; }
-  | expr = BuiltInCall() { return expr ; }
-  | expr = iriOrFunction() { return expr ; }
+  | expr = BuiltInCall() { return expr ; }  
+  | expr = iriOrFunction()  { return expr ; }
+
 // NOT  | gn = VarOrTerm()           { return asExpr(gn) ; }
 // Because of iriOrFunction 
-  | gn = RDFLiteral() { return asExpr(gn) ; }
-  | gn = NumericLiteral() { return asExpr(gn) ; }
-  | gn = BooleanLiteral() { return asExpr(gn) ; }
-  | gn = Var() { return asExpr(gn) ; }
+  | gn = RDFLiteral()      { return asExpr(gn) ; }
+  | gn = NumericLiteral()  { return asExpr(gn) ; }
+  | gn = BooleanLiteral()  { return asExpr(gn) ; }
+  | gn = Var()             { return asExpr(gn) ; }
   )
 }
+
 Expr BrackettedExpression() : { Expr expr ; }
 {
-    <LPAREN> expr = Expression() <RPAREN> { return expr ; }
+    <LPAREN> expr = Expression() <RPAREN>  { return expr ; }
 }
+
 Expr BuiltInCall() : { Expr expr ; Expr expr1 = null ; Expr expr2 = null ;
                        Node gn ; Token t ; ExprList a ; }
 {
@@ -1375,170 +1572,236 @@ Expr BuiltInCall() : { Expr expr ; Expr 
     { return new E_Str(expr) ; }
   | <LANG> <LPAREN> expr = Expression() <RPAREN>
     { return new E_Lang(expr) ; }
-  | <LANGMATCHES>
+
+  | <LANGMATCHES> 
        <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_LangMatches(expr1, expr2) ; }
+
   | <DTYPE> <LPAREN> expr = Expression() <RPAREN>
     { return new E_Datatype(expr) ; }
+
   | <BOUND> <LPAREN> gn = Var() <RPAREN>
     { return new E_Bound(new ExprVar(gn)) ; }
+
   | <IRI> <LPAREN> expr = Expression() <RPAREN>
     { return new E_IRI(expr) ; }
+
   | <URI> <LPAREN> expr = Expression() <RPAREN>
     { return new E_URI(expr) ; }
-  | <BNODE>
+
+  | <BNODE> 
     ( <LPAREN> expr1 = Expression() <RPAREN>
       { return new E_BNode(expr1) ; }
     |
       <NIL> { return new E_BNode() ; }
     )
+
   | <RAND> <NIL> { return new E_Random() ; }
-  | <ABS> <LPAREN> expr1 = Expression() <RPAREN> { return new E_NumAbs(expr1) ; }
+
+  | <ABS>  <LPAREN> expr1 = Expression() <RPAREN> { return new E_NumAbs(expr1) ; }
+    
   | <CEIL> <LPAREN> expr1 = Expression() <RPAREN> { return new E_NumCeiling(expr1) ; }
+    
   | <FLOOR> <LPAREN> expr1 = Expression() <RPAREN> { return new E_NumFloor(expr1) ; }
+    
   | <ROUND> <LPAREN> expr1 = Expression() <RPAREN> { return new E_NumRound(expr1) ; }
+    
   | <CONCAT> a = ExpressionList() { return new E_StrConcat(a) ; }
+    
   | expr = SubstringExpression() { return expr ; }
+    
   | <STRLEN> <LPAREN> expr1 = Expression() <RPAREN> { return new E_StrLength(expr1) ; }
+
   | expr = StrReplaceExpression() { return expr ; }
+    
   | <UCASE> <LPAREN> expr1 = Expression() <RPAREN> { return new E_StrUpperCase(expr1) ; }
+    
   | <LCASE> <LPAREN> expr1 = Expression() <RPAREN> { return new E_StrLowerCase(expr1) ; }
+    
   | <ENCODE_FOR_URI> <LPAREN> expr1 = Expression() <RPAREN> { return new E_StrEncodeForURI(expr1) ; }
+    
   | <CONTAINS> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrContains(expr1, expr2) ; }
+    
   | <STRSTARTS> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrStartsWith(expr1, expr2) ; }
+    
   | <STRENDS> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrEndsWith(expr1, expr2) ; }
-  | <STRBEFORE> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
+
+  | <STRBEFORE>  <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrBefore(expr1, expr2) ; }
-  | <STRAFTER> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
+
+  | <STRAFTER>    <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrAfter(expr1, expr2) ; }
+
   | <YEAR> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeYear(expr1) ; }
+    
   | <MONTH> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeMonth(expr1) ; }
+    
   | <DAY> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeDay(expr1) ; }
+    
   | <HOURS> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeHours(expr1) ; }
+    
   | <MINUTES> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeMinutes(expr1) ; }
+    
   | <SECONDS> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeSeconds(expr1) ; }
+    
   | <TIMEZONE> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeTimezone(expr1) ; }
   | <TZ> <LPAREN> expr1 = Expression() <RPAREN> { return new E_DateTimeTZ(expr1) ; }
-  | <NOW> <NIL> { return new E_Now() ; }
-  | <UUID> <NIL> { return new E_UUID() ; }
-  | <STRUUID> <NIL> { return new E_StrUUID() ; }
-  | <MD5> <LPAREN> expr1 = Expression() <RPAREN> { return new E_MD5(expr1) ; }
-  | <SHA1> <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA1(expr1) ; }
-  | <SHA256> <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA256(expr1) ; }
-  | <SHA384> <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA384(expr1) ; }
-  | <SHA512> <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA512(expr1) ; }
-  | <VERSION> <NIL> { return new E_Version(); }
+
+  | <NOW> <NIL>   { return new E_Now() ; }
+
+  | <UUID> <NIL>  { return new E_UUID() ; }
+  | <STRUUID> <NIL>  { return new E_StrUUID() ; }
+
+  | <MD5>         <LPAREN> expr1 = Expression() <RPAREN> { return new E_MD5(expr1) ; }
+  | <SHA1>        <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA1(expr1) ; }
+  | <SHA256>      <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA256(expr1) ; }
+
+  | <SHA384>      <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA384(expr1) ; }
+
+  | <SHA512>      <LPAREN> expr1 = Expression() <RPAREN> { return new E_SHA512(expr1) ; }
+
+  | <VERSION> <NIL>     { return new E_Version(); }
+
   | <COALESCE> a = ExpressionList()
     { return new E_Coalesce(a) ; }
-  | <IF> <LPAREN> expr = Expression() <COMMA>
-                  expr1 = Expression() <COMMA>
+    
+  | <CALL> a = ExpressionList()
+    { return new E_Call(a) ; }
+
+  | <IF> <LPAREN> expr = Expression() <COMMA> 
+                  expr1 = Expression() <COMMA> 
                   expr2 = Expression() <RPAREN>
     { return new E_Conditional(expr, expr1, expr2) ; }
+
   | <STRLANG> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrLang(expr1, expr2) ; }
+
   | <STRDT> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_StrDatatype(expr1, expr2) ; }
+
+
   | <SAME_TERM> <LPAREN> expr1 = Expression() <COMMA> expr2 = Expression() <RPAREN>
     { return new E_SameTerm(expr1, expr2) ; }
+
   | t = <IS_IRI> <LPAREN> expr = Expression() <RPAREN>
     { return new E_IsIRI(expr) ; }
+
   | t = <IS_URI> <LPAREN> expr = Expression() <RPAREN>
     { return new E_IsURI(expr) ; }
+
   | <IS_BLANK> <LPAREN> expr = Expression() <RPAREN>
     { return new E_IsBlank(expr) ; }
+
   | <IS_LITERAL> <LPAREN> expr = Expression() <RPAREN>
     { return new E_IsLiteral(expr) ; }
+
   | <IS_NUMERIC> <LPAREN> expr = Expression() <RPAREN>
     { return new E_IsNumeric(expr) ; }
+
   | // Regular expression matcher
     expr = RegexExpression() { return expr ; }
-  | expr = ExistsFunc() { return expr ; }
-  | expr = NotExistsFunc() { return expr ; }
+
+  | expr = ExistsFunc()      { return expr ; }
+
+  | expr = NotExistsFunc()   { return expr ; }
 }
+
 Expr RegexExpression() :
 { Expr expr ; Expr patExpr = null ; Expr flagsExpr = null ; }
 {
-    <REGEX>
-    <LPAREN>
-      expr = Expression()
+    <REGEX> 
+    <LPAREN> 
+      expr = Expression() 
       <COMMA>
       patExpr = Expression()
       ( <COMMA> flagsExpr = Expression() ) ?
     <RPAREN>
       { return new E_Regex(expr, patExpr, flagsExpr) ; }
 }
+
 Expr SubstringExpression() :
 { Expr expr1 ; Expr expr2 = null ; Expr expr3 = null ; }
 {
     <SUBSTR>
-    <LPAREN>
-      expr1 = Expression()
+    <LPAREN> 
+      expr1 = Expression() 
       <COMMA>
       expr2 = Expression()
       ( <COMMA> expr3 = Expression() ) ?
     <RPAREN>
       { return new E_StrSubstring(expr1, expr2, expr3) ; }
 }
+
 Expr StrReplaceExpression() :
 { Expr expr1 ; Expr expr2 = null ; Expr expr3 = null ; Expr expr4 = null ;}
 {
   <REPLACE>
-  <LPAREN>
-  expr1 = Expression()
+  <LPAREN> 
+  expr1 = Expression() 
   <COMMA> expr2 = Expression()
   <COMMA> expr3 = Expression()
   ( <COMMA> expr4 = Expression() ) ?
-  <RPAREN>
+  <RPAREN> 
   { return new E_StrReplace(expr1,expr2,expr3,expr4) ; }
 }
+
 Expr ExistsFunc() : { Element el ; }
 {
    <EXISTS>
    el = GroupGraphPattern()
    { return createExprExists(el) ; }
 }
+
 Expr NotExistsFunc() : { Element el ; }
 {
    <NOT> <EXISTS>
    el = GroupGraphPattern()
    { return createExprNotExists(el) ; }
 }
+
 Expr Aggregate() : { Aggregator agg = null ; String sep = null ;
                      boolean distinct = false ;
-                     Expr expr = null ; Expr expr2 = null ;
+                     Expr expr = null ;  Expr expr2 = null ;
                      ExprList a = new ExprList() ;
                      ExprList ordered = new ExprList() ;
                      Token t ; }
 {
   // Count is special because of COUNT(*)
   // GROUP_CONCAT is special because of separator=
-  ( t = <COUNT> <LPAREN>
+
+  ( t = <COUNT> <LPAREN> 
     ( <DISTINCT> { distinct = true ; } )?
     ( <STAR> | expr = Expression() )
     <RPAREN>
     { if ( expr == null ) { agg = AggregatorFactory.createCount(distinct) ; }
       if ( expr != null ) { agg = AggregatorFactory.createCountExpr(distinct, expr) ; }
     }
-  | t = <SUM> <LPAREN> ( <DISTINCT> { distinct = true ; } )? expr = Expression() <RPAREN>
+
+  | t = <SUM> <LPAREN> ( <DISTINCT> { distinct = true ; } )? expr = Expression() <RPAREN> 
     { agg = AggregatorFactory.createSum(distinct, expr) ; }
+
   | t = <MIN> <LPAREN> ( <DISTINCT> { distinct = true ; } )? expr = Expression() <RPAREN>
     { agg = AggregatorFactory.createMin(distinct, expr) ; }
+
   | t = <MAX> <LPAREN> ( <DISTINCT> { distinct = true ; } )? expr = Expression() <RPAREN>
     { agg = AggregatorFactory.createMax(distinct, expr) ; }
+
   | t = <AVG> <LPAREN> ( <DISTINCT> { distinct = true ; } )? expr = Expression() <RPAREN>
     { agg = AggregatorFactory.createAvg(distinct, expr) ; }
+
   | t = <SAMPLE> <LPAREN> ( <DISTINCT> { distinct = true ; } )? expr = Expression() <RPAREN>
     { agg = AggregatorFactory.createSample(distinct, expr) ; }
+
   | t = <GROUP_CONCAT>
     <LPAREN>
     (t = <DISTINCT> { distinct = true ; })?
-    expr = Expression() { a.add(expr) ; }
+    expr = Expression() { a.add(expr) ; } 
        // JavcaCC 5.0 - rewriting as LL(1) didn't work - code generated was wrong
     (LOOKAHEAD(2)
-       ( <SEMICOLON> <SEPARATOR> <EQ> sep=String()
+       ( <SEMICOLON>  <SEPARATOR> <EQ> sep=String()
            (<SEMICOLON> <ORDER><BY> expr2 = Expression() { ordered.add(expr2) ; })?
        )
        |
@@ -1547,6 +1810,7 @@ Expr Aggregate() : { Aggregator agg = nu
     <RPAREN>
     { agg = AggregatorFactory.createGroupConcat(distinct, expr, sep, ordered) ; }
    )
+
    {
      if ( ! allowAggregatesInExpressions )
             throwParseException("Aggregate expression not legal at this point",
@@ -1555,32 +1819,39 @@ Expr Aggregate() : { Aggregator agg = nu
    { Expr exprAgg = getQuery().allocAggregate(agg) ;
      return exprAgg ; }
 }
+
 // See also FunctionCall.
 // The case of "q:name()" or "q:agg()" or just "q:name"
 // by expanding out FunctionCall()
-Expr iriOrFunction() : { String iri ; ExprList a = null ;
-                         ExprList params = null ;
+
+Expr iriOrFunction() : { String iri ; ExprList a = null ; 
+                         ExprList params = null ; 
                          boolean distinct = false ; }
 {
   iri = iri()
   (a = ArgList())?
-  { if ( a == null )
+  { if ( a == null ) 
        return asExpr(createNode(iri)) ;
     return new E_Function(iri, a) ;
   }
 }
+
+
+
 Node RDFLiteral() : { Token t ; String lex = null ; }
 {
   lex = String()
   // Optional lang tag and datatype.
   { String lang = null ; String uri = null ; }
   (
-    ( t = <LANGTAG> { lang = stripChars(t.image, 1) ; } )
+    ( t = <LANGTAG>  { lang = stripChars(t.image, 1) ; } )
   |
     ( <DATATYPE> uri = iri() )
   )?
     { return createLiteral(lex, lang, uri) ; }
-}
+} 
+
+
 Node NumericLiteral() : { Node n ; }
 {
   (
@@ -1589,31 +1860,38 @@ Node NumericLiteral() : { Node n ; }
   | n = NumericLiteralNegative()
   )
   { return n ; }
+
 }
+
 Node NumericLiteralUnsigned() : { Token t ; }
 {
   t = <INTEGER> { return createLiteralInteger(t.image) ; }
 | t = <DECIMAL> { return createLiteralDecimal(t.image) ; }
-| t = <DOUBLE> { return createLiteralDouble(t.image) ; }
+| t = <DOUBLE>  { return createLiteralDouble(t.image) ; }
 }
+
 Node NumericLiteralPositive() : { Token t ; }
 {
   t = <INTEGER_POSITIVE> { return createLiteralInteger(t.image) ; }
 | t = <DECIMAL_POSITIVE> { return createLiteralDecimal(t.image) ; }
-| t = <DOUBLE_POSITIVE> { return createLiteralDouble(t.image) ; }
+| t = <DOUBLE_POSITIVE>  { return createLiteralDouble(t.image) ; }
 }
+
 Node NumericLiteralNegative() : { Token t ; }
 {
   t = <INTEGER_NEGATIVE> { return createLiteralInteger(t.image) ; }
 | t = <DECIMAL_NEGATIVE> { return createLiteralDecimal(t.image) ; }
-| t = <DOUBLE_NEGATIVE> { return createLiteralDouble(t.image) ; }
+| t = <DOUBLE_NEGATIVE>  { return createLiteralDouble(t.image) ; }
 }
+
+
 Node BooleanLiteral() : {}
 {
   <TRUE> { return XSD_TRUE ; }
  |
   <FALSE> { return XSD_FALSE ; }
 }
+
 String String() : { Token t ; String lex ; }
 {
   ( t = <STRING_LITERAL1> { lex = stripQuotes(t.image) ; }
@@ -1622,16 +1900,18 @@ String String() : { Token t ; String lex
   | t = <STRING_LITERAL_LONG2> { lex = stripQuotes3(t.image) ; }
   )
     {
-      lex = unescapeStr(lex, t.beginLine, t.beginColumn) ;
+      lex = unescapeStr(lex,  t.beginLine, t.beginColumn) ;
       return lex ;
     }
 }
+
 String iri() : { String iri ; }
 {
   iri = IRIREF() { return iri ; }
 |
   iri = PrefixedName() { return iri ; }
 }
+
 String PrefixedName() : { Token t ; }
 {
   ( t = <PNAME_LN>
@@ -1641,292 +1921,345 @@ String PrefixedName() : { Token t ; }
     { return resolvePName(t.image, t.beginLine, t.beginColumn) ; }
   )
 }
-Node BlankNode() : { Token t = null ; }
+
+Node BlankNode() :  { Token t = null ; }
 {
   t = <BLANK_NODE_LABEL>
-    { return createBNode(t.image, t.beginLine, t.beginColumn) ; }
+    { return createBNode(t.image, t.beginLine, t.beginColumn) ; }  
 |
 //  <LBRACKET> <RBRACKET> { return createBNode(t.beginLine, t.beginColumn) ; }
   t = <ANON> { return createBNode(t.beginLine, t.beginColumn) ; }
+
 }
+
 String IRIREF() : { Token t ; }
 {
   t = <IRIref>
   { return resolveQuotedIRI(t.image, t.beginLine, t.beginColumn) ; }
 }
+
 // ------------------------------------------
 // Tokens
+
 // Comments and whitespace
+
 SKIP : { " " | "\t" | "\n" | "\r" | "\f" }
+
 SPECIAL_TOKEN :
 { <SINGLE_LINE_COMMENT: "#" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? > }
-TOKEN: {
+
+
+
+TOKEN: { 
   <#WS: " " | "\t" | "\n" | "\r" | "\f">
 |
   // Whitespace or comment.
   <#WSC: <WS> | <SINGLE_LINE_COMMENT> >
 }
+
 // Main tokens */
+
 TOKEN:
 {
    // Includes # for relative URIs
-   <IRIref: "<" (~[ ">","<", "\"", "{", "}", "^", "\\", "|", "`",
+   <IRIref:       "<" (~[ ">","<", "\"", "{", "}", "^", "\\", "|", "`", 
                       "\u0000"-"\u0020"])* ">" >
-| <PNAME_NS: (<PN_PREFIX>)? ":" >
-| <PNAME_LN: <PNAME_NS> <PN_LOCAL> >
-| <BLANK_NODE_LABEL: "_:" (<PN_CHARS_U> | ["0"-"9"]) ((<PN_CHARS>|".")* <PN_CHARS>)? >
-| <VAR1: "?" <VARNAME> >
-| <VAR2: "$" <VARNAME> >
-| <LANGTAG: <AT> (<A2Z>)+("-" (<A2ZN>)+)* >
-| <#A2Z: ["a"-"z","A"-"Z"]>
-| <#A2ZN: ["a"-"z","A"-"Z","0"-"9"]>
+|  <PNAME_NS: (<PN_PREFIX>)? ":" >
+|  <PNAME_LN: <PNAME_NS> <PN_LOCAL> >
+|  <BLANK_NODE_LABEL: "_:" (<PN_CHARS_U> | ["0"-"9"]) ((<PN_CHARS>|".")* <PN_CHARS>)?  >
+|  <VAR1: "?" <VARNAME> >
+|  <VAR2: "$" <VARNAME> >
+|  <LANGTAG: <AT> (<A2Z>)+("-" (<A2ZN>)+)* >
+|  <#A2Z: ["a"-"z","A"-"Z"]>
+|  <#A2ZN: ["a"-"z","A"-"Z","0"-"9"]>
 }
+
 // -------------------------------------------------
 // Keyworks : includes operators that are words and should be
 // before general things like IDENTIFIER which swallow almost
 // anything
-TOKEN : { <KW_A: "a" > }
+
+TOKEN : { <KW_A:  "a" > }
+
 TOKEN [IGNORE_CASE] :
 {
 // Prologue
-   < BASE: "base" >
-| < PREFIX: "prefix" >
+   < BASE:        "base" >
+|  < PREFIX:      "prefix" >
+
 // Result forms
-| < SELECT: "select" >
-| < DISTINCT: "distinct" >
-| < REDUCED: "reduced" >
-| < DESCRIBE: "describe" >
-| < CONSTRUCT: "construct" >
-| < ASK: "ask" >
-| < LIMIT: "limit" >
-| < OFFSET: "offset" >
-| < ORDER: "order" >
-| < BY: "by" >
-| < VALUES: "values" >
-| < UNDEF: "undef" >
-| < ASC: "asc" >
-| < DESC: "desc" >
+|  < SELECT:      "select" >
+|  < DISTINCT:    "distinct" >
+|  < REDUCED:     "reduced" >
+|  < DESCRIBE:    "describe" >
+|  < CONSTRUCT:   "construct" >
+|  < ASK:         "ask" >
+
+|  < LIMIT:       "limit" >
+|  < OFFSET:      "offset" >
+|  < ORDER:       "order" >
+|  < BY:          "by" >
+|  < VALUES:      "values" >
+|  < UNDEF:       "undef" >
+
+|  < ASC:         "asc" >
+|  < DESC:        "desc" >
+
 // Dataset
-| < NAMED: "named" >
-| < FROM: "from" >
+|  < NAMED:       "named" >
+|  < FROM:        "from" >
+
 // Graph pattern operators 
-| < WHERE: "where" >
-| < AND: "and" >
-| < GRAPH: "graph" >
-| < OPTIONAL: "optional" >
-| < UNION: "union" >
-| < MINUS_P: "minus" >
-| < BIND: "bind" >
-| < SERVICE: "service" >
-| < LET: "let" >
-| < FETCH: "fetch" >
-| < EXISTS: "exists" >
-| < NOT: "not" >
+|  < WHERE:       "where" >
+|  < AND:         "and" >
+|  < GRAPH:       "graph" >
+|  < OPTIONAL:    "optional" >
+|  < UNION:       "union" >
+|  < MINUS_P:     "minus" >
+|  < BIND:        "bind" >
+|  < SERVICE:     "service" >
+
+|  < LET:         "let" >
+|  < FETCH:       "fetch" >
+|  < EXISTS:      "exists" >
+|  < NOT:         "not" >
 //|  < UNSAID:      "unsaid" >
-| < AS: "as" >
-| < GROUP: "group" >
-| < HAVING: "having" >
-| < SEPARATOR: "separator" >
-| < AGG: "agg" >
-| < COUNT: "count" >
-| < MIN: "min" >
-| < MAX: "max" >
-| < SUM: "sum" >
-| < AVG: "avg" >
-| < STDDEV: "stdev" >
-| < SAMPLE: "sample" >
-| < GROUP_CONCAT: "group_concat" >
-| < FILTER: "filter" >
+|  < AS:          "as" >
+|  < GROUP:       "group" >
+|  < HAVING:      "having" >
+|  < SEPARATOR:   "separator" >
+|  < AGG:         "agg" >
+|  < COUNT:       "count" >
+|  < MIN:         "min" >
+|  < MAX:         "max" >
+|  < SUM:         "sum" >
+|  < AVG:         "avg" >
+|  < STDDEV:      "stdev" >
+|  < SAMPLE:      "sample" >
+|  < GROUP_CONCAT: "group_concat" >
+
+|  < FILTER:      "filter" >
+
 // Expression operators
-| < BOUND: "bound" >
-| < COALESCE: "coalesce" >
-| < IN: "in" >
-| < IF: "if" >
-| < BNODE: "bnode" >
-| < IRI: "iri" >
-| < URI: "uri" >
-| < CAST: "cast" >
-| < CALL: "call" >
-| < MULTI: "multi" >
-| < SHORTEST: "shortest" >
-| < STR: "str" >
-| < STRLANG: "strlang" >
-| < STRDT: "strdt" >
-| < DTYPE: "datatype" >
-| < LANG: "lang" >
-| < LANGMATCHES: "langmatches" >
-| < IS_URI: "isURI" >
-| < IS_IRI: "isIRI" >
-| < IS_BLANK: "isBlank" >
-| < IS_LITERAL: "isLiteral" >
-| < IS_NUMERIC: "isNumeric" >
-| < REGEX: "regex" >
-| < SAME_TERM: "sameTerm" >
-| < RAND: "RAND" >
-| < ABS: "ABS" >
-| < CEIL: "CEIL" >
-| < FLOOR: "FLOOR" >
-| < ROUND: "ROUND" >
-| < CONCAT: "CONCAT" >
-| < SUBSTR: "SUBSTR" >
-| < STRLEN: "STRLEN" >
-| < REPLACE: "REPLACE" >
-| < UCASE: "UCASE" >
-| < LCASE: "LCASE" >
-| < ENCODE_FOR_URI: "ENCODE_FOR_URI" >
-| < CONTAINS: "CONTAINS" >
-| < STRSTARTS: "STRSTARTS" >
-| < STRENDS: "STRENDS" >
-| < STRBEFORE: "STRBEFORE" >
-| < STRAFTER : "STRAFTER" >
-| < YEAR: "YEAR" >
-| < MONTH: "MONTH" >
-| < DAY: "DAY" >
-| < HOURS: "HOURS" >
-| < MINUTES: "MINUTES" >
-| < SECONDS: "SECONDS" >
-| < TIMEZONE: "TIMEZONE" >
-| < TZ: "TZ" >
-| < NOW: "NOW" >
-| < UUID: "UUID" >
-| < STRUUID: "STRUUID" >
-| < VERSION: "VERSION" >
-| < MD5: "MD5" >
-| < SHA1: "SHA1" >
-| < SHA224: "SHA224" >
-| < SHA256: "SHA256" >
-| < SHA384: "SHA384" >
-| < SHA512: "SHA512" >
-| < TRUE: "true" >
-| < FALSE: "false" >
+|  < BOUND:       "bound" >
+|  < COALESCE:    "coalesce" >
+|  < IN:          "in" >
+|  < IF:          "if" >
+|  < BNODE:       "bnode" >
+|  < IRI:         "iri" >
+|  < URI:         "uri" >
+
+|  < CAST:        "cast" >
+|  < CALL:        "call" >
+|  < MULTI:       "multi" >
+|  < SHORTEST:    "shortest" >
+
+|  < STR:         "str" >
+|  < STRLANG:     "strlang" >
+|  < STRDT:       "strdt" >
+|  < DTYPE:       "datatype" >
+|  < LANG:        "lang" >
+|  < LANGMATCHES: "langmatches" >
+|  < IS_URI:      "isURI" >
+|  < IS_IRI:      "isIRI" >
+|  < IS_BLANK:    "isBlank" >
+|  < IS_LITERAL:  "isLiteral" >
+|  < IS_NUMERIC:  "isNumeric" >
+|  < REGEX:       "regex" >
+|  < SAME_TERM:   "sameTerm" >
+
+|  < RAND:        "RAND" >
+|  < ABS:         "ABS" >
+|  < CEIL:        "CEIL" >
+|  < FLOOR:       "FLOOR" >
+|  < ROUND:       "ROUND" >
+|  < CONCAT:      "CONCAT" >
+|  < SUBSTR:      "SUBSTR" >
+|  < STRLEN:      "STRLEN" >
+|  < REPLACE:     "REPLACE" >
+|  < UCASE:       "UCASE" >
+|  < LCASE:       "LCASE" >
+|  < ENCODE_FOR_URI:      "ENCODE_FOR_URI" >
+|  < CONTAINS:    "CONTAINS" >
+|  < STRSTARTS:   "STRSTARTS" >
+|  < STRENDS:     "STRENDS" >
+|  < STRBEFORE:   "STRBEFORE" >
+|  < STRAFTER :   "STRAFTER" >
+|  < YEAR:        "YEAR" >
+|  < MONTH:       "MONTH" >
+|  < DAY:         "DAY" >
+|  < HOURS:       "HOURS" >
+|  < MINUTES:     "MINUTES" >
+|  < SECONDS:     "SECONDS" >
+|  < TIMEZONE:    "TIMEZONE" >
+|  < TZ:          "TZ" >
+|  < NOW:         "NOW" >
+|  < UUID:        "UUID" >
+|  < STRUUID:     "STRUUID" >
+|  < VERSION:     "VERSION" >
+
+| < MD5:          "MD5" >
+| < SHA1:         "SHA1" >
+| < SHA224:       "SHA224" >
+| < SHA256:       "SHA256" >
+| < SHA384:       "SHA384" >
+| < SHA512:       "SHA512" >
+
+|  < TRUE:        "true" >
+|  < FALSE:       "false" >
 }
+
 // SPARQL/Update parts.
+
 TOKEN [IGNORE_CASE] :
 {
-  < DATA: "data" >
-| < INSERT: "insert">
-| < DELETE: "delete" >
-| < INSERT_DATA: <INSERT> (<WSC>)* <DATA> >
-| < DELETE_DATA: <DELETE> (<WSC>)* <DATA> >
+  < DATA:	      "data" >
+| < INSERT:       "insert">
+| < DELETE:       "delete" >
+
+| < INSERT_DATA:  <INSERT> (<WSC>)* <DATA> >
+| < DELETE_DATA:  <DELETE> (<WSC>)* <DATA> >
 | < DELETE_WHERE: <DELETE> (<WSC>)* <WHERE> >
-| < MODIFY: "modify">
-| < LOAD: "load" >
-| < CLEAR: "clear" >
-| < CREATE: "create" >
-| < ADD: "add" >
-| < MOVE: "move" >
-| < COPY: "copy" >
-| < META: "meta" >
-| < SILENT: "silent" >
-| < DROP: "drop" >
-| < INTO: "into" >
-| < TO: "to" >
-| < DFT: "default" >
+
+| < MODIFY:      "modify">
+| < LOAD:         "load" >
+| < CLEAR:        "clear" >
+| < CREATE:       "create" >
+| < ADD:          "add" >
+| < MOVE:         "move" >
+| < COPY:         "copy" >
+| < META:         "meta" >
+| < SILENT:       "silent" >
+| < DROP:         "drop" >
+| < INTO:         "into" >
+| < TO:           "to" >
+| < DFT:          "default" >
 //| < NAMED:        "named" >
-| < ALL: "all" >
-| < WITH: "with" >
-| < USING: "using" >
+| < ALL:          "all" >
+| < WITH:         "with" >
+| < USING:        "using" >
+
 //| < BEGIN:       "begin" >
 //| < COMMIT:      "commit" >
 //| < ABORT:       "abort" >
 }
+
 // -------------------------------------------------
+
 TOKEN :
 {
   < #DIGITS: (["0"-"9"])+>
 | < INTEGER: <DIGITS> >
 //| < DECIMAL: ( <DIGITS> "." (<DIGITS>)* | "." <DIGITS> ) >
 | < DECIMAL: (<DIGITS>)? "." <DIGITS> >
-| < DOUBLE: // Required exponent.
+| < DOUBLE:   // Required exponent.
       (
         (["0"-"9"])+ "." (["0"-"9"])* <EXPONENT>
         | "." (["0"-"9"])+ (<EXPONENT>)
         | (["0"-"9"])+ <EXPONENT>
       )
       >
+
 | < INTEGER_POSITIVE: <PLUS> <INTEGER> >
 | < DECIMAL_POSITIVE: <PLUS> <DECIMAL> >
-| < DOUBLE_POSITIVE: <PLUS> <DOUBLE> >
+| < DOUBLE_POSITIVE:  <PLUS> <DOUBLE> >
+
 | < INTEGER_NEGATIVE: <MINUS> <INTEGER> >
 | < DECIMAL_NEGATIVE: <MINUS> <DECIMAL> >
-| < DOUBLE_NEGATIVE: <MINUS> <DOUBLE> >
+| < DOUBLE_NEGATIVE:  <MINUS> <DOUBLE> >
+
 | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
 | < #QUOTE_3D: "\"\"\"">
 | < #QUOTE_3S: "'''">
 | <ECHAR: "\\" ( "t"|"b"|"n"|"r"|"f"|"\\"|"\""|"'") >
-| < STRING_LITERAL1:
+| < STRING_LITERAL1: 
       // Single quoted string
-      "'" ( (~["'","\\","\n","\r"]) | <ECHAR> )* "'" >
+      "'" ( (~["'","\\","\n","\r"]) | <ECHAR> )* "'" > 
 | < STRING_LITERAL2:
     // Double quoted string
       "\"" ( (~["\"","\\","\n","\r"]) | <ECHAR> )* "\"" >
 | < STRING_LITERAL_LONG1:
-     <QUOTE_3S>
+     <QUOTE_3S> 
       ( ("'" | "''")? (~["'","\\"] | <ECHAR> ))*
      <QUOTE_3S> >
-| < STRING_LITERAL_LONG2:
-     <QUOTE_3D>
+
+| < STRING_LITERAL_LONG2: 
+     <QUOTE_3D> 
       ( ("\"" | "\"\"")? (~["\"","\\"] | <ECHAR> ))*
      <QUOTE_3D> >
 }
+
 TOKEN :
 {
-  < LPAREN: "(" >
-| < RPAREN: ")" >
+  < LPAREN:    "(" >
+| < RPAREN:    ")" >
+
 // All the stuff for NUL is needed just to make a 
 // single list "() ." as a triple pattern illegal.
 // It leads to a lot of extra work.
 // Similarly [].
+
 | <NIL: <LPAREN> (<WSC>)* <RPAREN> >
-| < LBRACE: "{" >
-| < RBRACE: "}" >
-| < LBRACKET: "[" >
-| < RBRACKET: "]" >
-| < ANON: <LBRACKET> (<WSC>)* <RBRACKET> >
+
+| < LBRACE:    "{" >
+| < RBRACE:    "}" >
+
+| < LBRACKET:  "[" >
+| < RBRACKET:  "]" >
+| < ANON:      <LBRACKET> (<WSC>)* <RBRACKET> >
+
 | < SEMICOLON: ";" >
-| < COMMA: "," >
-| < DOT: "." >
-| < EQ: "=" >
-| < NE: "!=" >
-| < GT: ">" >
-| < LT: "<" >
-| < LE: "<=" > // Maybe: | "=>" >
-| < GE: ">=" > // Maybe: | "=<" >
-| < BANG: "!" >
-| < TILDE: "~" >
-| < COLON: ":" >
-| < SC_OR: "||" >
-| < SC_AND: "&&" >
-| < PLUS: "+" >
-| < MINUS: "-" >
-| < STAR: "*" >
-| < SLASH: "/" >
+| < COMMA:     "," >
+| < DOT:       "." >
+| < EQ:      "=" >
+| < NE:      "!=" >
+| < GT:      ">" >
+| < LT:      "<" >
+| < LE:      "<=" >    // Maybe: | "=>" >
+| < GE:      ">=" >    // Maybe: | "=<" >
+
+| < BANG:    "!" >
+| < TILDE:   "~" >
+| < COLON:   ":" >
+
+| < SC_OR:   "||" >
+| < SC_AND:  "&&" >
+
+| < PLUS:    "+" >
+| < MINUS:   "-" >
+| < STAR:    "*" >
+| < SLASH:   "/" >
+
 //| < AMP: "&" >
 //| < REM: "%" >
+
 | < DATATYPE: "^^">
 | < AT: "@">
-| < ASSIGN: ":=">
+| < ASSIGN:     ":=">
+
 // Path related
-| < VBAR: "|" >
-| < CARAT: "^" >
-| < FPATH: "->" >
-| < RPATH: "<-" >
-| < QMARK: "?" >
+| < VBAR:     "|" >
+| < CARAT:    "^" >
+| < FPATH:    "->" >
+| < RPATH:    "<-" >
+| < QMARK:    "?" >
 }
+
 // See XML chars.txt for notes
+
 TOKEN:
 {
-  // ARQ extensions to the PN_LOCAL token.
+  // 1 extensions to the PN_LOCAL token.
   < #HEX: ["0"-"9"] | ["A"-"F"] | ["a"-"f"] >
 |
   < #PERCENT: "%" <HEX> <HEX> >
 |
   // Prefixed Name, Local Part, charcater escape sequences
   // Align with QueryParseBase unescapePName.
-  < #PN_LOCAL_ESC: "\\"
-          ( "_" |
-            "~" | "." | "-" | "!" | "$" | "&" | "'" |
-           "(" | ")" | "*" | "+" | "," | ";" | "=" |
+  < #PN_LOCAL_ESC: "\\" 
+          ( "_" | 
+            "~" | "." | "-" | "!" | "$" | "&" | "'" | 
+           "(" | ")" | "*" | "+" | "," | ";" | "=" | 
            "/" | "?" | "#" | "@" | "%" ) >
 |
   // XML 1.1 NCNameStartChar without "_"
@@ -1935,7 +2268,7 @@ TOKEN:
           ["\u00C0"-"\u00D6"] | ["\u00D8"-"\u00F6"] | ["\u00F8"-"\u02FF"] |
           ["\u0370"-"\u037D"] | ["\u037F"-"\u1FFF"] |
           ["\u200C"-"\u200D"] | ["\u2070"-"\u218F"] | ["\u2C00"-"\u2FEF"] |
-          ["\u3001"-"\uD7FF"] | ["\uF900"-"\uFFFD"]
+          ["\u3001"-"\uD7FF"] | ["\uF900"-"\uFFFD"] 
           >
           // [#x10000-#xEFFFF]
 |
@@ -1946,20 +2279,21 @@ TOKEN:
               ["\u0300"-"\u036F"] | ["\u203F"-"\u2040"] ) >
 |
   // No leading "_", no trailing ".", can have dot inside prefix name.
-  <#PN_PREFIX: <PN_CHARS_BASE> ((<PN_CHARS>|".")* <PN_CHARS>)? >
+  <#PN_PREFIX: <PN_CHARS_BASE> ((<PN_CHARS>|".")* <PN_CHARS>)?  >
 |
-  <#PLX: <PERCENT> | <PN_LOCAL_ESC> >
+  <#PLX:  <PERCENT> | <PN_LOCAL_ESC> >
 |
   // If goes ahead, consolidate
-  <#PN_LOCAL: (<PN_CHARS_U> | ["0"-"9"] | <PLX> )
-              ( (<PN_CHARS>|"."| <PLX> )*
-                (<PN_CHARS>|<PLX>) ) ? >
+  <#PN_LOCAL: (<PN_CHARS_U> | ["0"-"9"] | <PLX> ) 
+              ( (<PN_CHARS>|"."| <PLX> )* 
+                (<PN_CHARS>|<PLX>) )?  >
 |
   // NCNAME without "-" and ".", allowing leading digits.
   <#VARNAME: ( <PN_CHARS_U> | ["0"-"9"] )
              ( <PN_CHARS_U> | ["0"-"9"] | "\u00B7" |
                ["\u0300"-"\u036F"] | ["\u203F"-"\u2040"] )* >
 }
+
 // Catch-all tokens.  Must be last.  
 // Any non-whitespace.  Causes a parser exception, rather than a
 // token manager error (with hidden line numbers).
@@ -1968,6 +2302,7 @@ TOKEN:
 {
   <#UNKNOWN: (~[" ","\t","\n","\r","\f" ])+ >
 }
+
 /*
 # Local Variables:
 # tab-width: 4

Modified: jena/trunk/jena-arq/Grammar/master.jj
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/Grammar/master.jj?rev=1353021&r1=1353020&r2=1353021&view=diff
==============================================================================
--- jena/trunk/jena-arq/Grammar/master.jj (original)
+++ jena/trunk/jena-arq/Grammar/master.jj Fri Jun 22 20:33:52 2012
@@ -1812,6 +1812,11 @@ Expr BuiltInCall() : { Expr expr ; Expr 
 
   | <COALESCE> a = ExpressionList()
     { return new E_Coalesce(a) ; }
+    
+#if ARQ
+  | <CALL> a = ExpressionList()
+    { return new E_Call(a) ; }
+#endif
 
   | <IF> <LPAREN> expr = Expression() <COMMA> 
                   expr1 = Expression() <COMMA> 

Modified: jena/trunk/jena-arq/ReleaseNotes.txt
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/ReleaseNotes.txt?rev=1353021&r1=1353020&r2=1353021&view=diff
==============================================================================
--- jena/trunk/jena-arq/ReleaseNotes.txt (original)
+++ jena/trunk/jena-arq/ReleaseNotes.txt Fri Jun 22 20:33:52 2012
@@ -5,6 +5,9 @@ ChangeLog for ARQ
 ==== ARQ 2.9.2
 
 + Significant speed-up of MINUS queries (JENA-266) - contribution from Paul Gearon (@quoll). 
++ Log warning messages generated by failures in SERVICE clauses now include the URI of the
+  service that failed (JENA-269) - suggestion by Claude Warren
++ Support for dynamic function invocation built-in CALL() when using ARQ language
 
 ==== ARQ 2.9.1
 

Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/E_Call.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/E_Call.java?rev=1353021&r1=1353020&r2=1353021&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/E_Call.java (original)
+++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/E_Call.java Fri Jun 22 20:33:52 2012
@@ -18,15 +18,25 @@
 
 package com.hp.hpl.jena.sparql.expr;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List ;
+import java.util.Map;
 
-import com.hp.hpl.jena.sparql.ARQNotImplemented ;
+import com.hp.hpl.jena.sparql.ARQInternalErrorException;
 import com.hp.hpl.jena.sparql.engine.binding.Binding ;
 import com.hp.hpl.jena.sparql.function.FunctionEnv ;
+import com.hp.hpl.jena.sparql.util.Context;
 
+/**
+ * ARQ extension to SPARQL which provides for dynamic function invocation
+ */
 public class E_Call extends ExprFunctionN
 {
     private static final String symbol = "call" ;
+    private Map<String,Expr> functionCache = new HashMap<String, Expr>();
+    private Expr identExpr;
+    private List<Expr> argExprs;
 
     public E_Call(ExprList args)
     {
@@ -36,22 +46,71 @@ public class E_Call extends ExprFunction
     protected E_Call(String sym, ExprList args)
     {
         super(sym, args) ;
+        if (args.size() == 0) {
+        	identExpr = null;
+        } else {
+        	identExpr = args.get(0);
+        	argExprs = new ArrayList<Expr>();
+        	for (int i = 1; i < args.size(); i++) {
+        		argExprs.add(args.get(i));
+        	}
+        }
     }
 
     @Override
     public NodeValue evalSpecial(Binding binding, FunctionEnv env)
     {
-        throw new ARQNotImplemented() ;
-    }
-    
-    @Override
-    protected NodeValue eval(List<NodeValue> args)
-    {
-        throw new ARQNotImplemented() ;
+        //No argument returns unbound
+        if (identExpr == null) return null;
+        
+        //One/More arguments means invoke a function dynamically
+        NodeValue func = identExpr.eval(binding, env);
+        if (func == null) throw new ExprEvalException("CALL: Function identifier unbound");
+        if (func.isIRI()) {
+        	Expr e = buildFunction(func.getNode().getURI(), argExprs, env.getContext());
+        	if (e == null) throw new ExprEvalException("CALL: Function identifier <" + func.getNode().getURI() + "> does not identify a known function");
+        	//Calling this may throw an error which we will just let bubble up
+        	return e.eval(binding, env);
+        } else {
+        	throw new ExprEvalException("CALL: Function identifier not an IRI");
+        }
     }
      
     
     @Override
     protected Expr copy(ExprList newArgs)       { return new E_Call(newArgs) ; }
 
+	@Override
+	protected NodeValue eval(List<NodeValue> args) {
+		if (args.size() == 0) return null; //Can evaluate in this form only if empty arg list, otherwise error
+		throw new ARQInternalErrorException();
+	}
+	    
+	/**
+	 * Returns the expr representing the dynamic function to be invoked
+	 * <p>
+	 * Uses caching wherever possible to avoid 
+	 * </p>
+	 */
+    private Expr buildFunction(String functionIRI, List<Expr> args, Context cxt)
+    {
+    	//Use our cached version of the expression wherever possible
+    	if (functionCache.containsKey(functionIRI))	{
+    		return functionCache.get(functionIRI);
+    	}    	
+    	
+    	//Otherwise generate a new function and cache it
+    	try
+    	{
+    		E_Function e = new E_Function(functionIRI, new ExprList(args));
+    		e.buildFunction(cxt);
+        	functionCache.put(functionIRI, e);
+        	return e;
+    	} catch (Throwable e) {
+    		//Anything goes wrong in creating the function cache a null so we don't retry every time we see this IRI
+    		functionCache.put(functionIRI, null);
+    		return null;
+    	}
+        
+    }
 }