@@ -12,9 +12,10 @@ import type {
1212 SparqlGrammarRule ,
1313 SparqlRule ,
1414} from '../Sparql11types' ;
15- import { builtInCall } from './builtIn' ;
15+ import { aggregate , builtInCall } from './builtIn' ;
1616import {
1717 var_ ,
18+ varOrTerm ,
1819} from './general' ;
1920import {
2021 booleanLiteral ,
@@ -24,9 +25,7 @@ import {
2425 numericLiteralPositive ,
2526 rdfLiteral ,
2627} from './literals' ;
27-
28- const infixOperators = new Set ( [ '||' , '&&' , '=' , '!=' , '<' , '>' , '<=' , '>=' , 'in' , 'notin' , '+' , '-' , '*' , '/' ] ) ;
29- const prefixOperator = new Set ( [ '!' , 'UPLUS' , 'UMINUS' ] ) ;
28+ import { groupGraphPattern } from './whereClause' ;
3029
3130/**
3231 * [[71]](https://www.w3.org/TR/sparql11-query/#rArgList)
@@ -64,13 +63,27 @@ export const argList: SparqlRule<'argList', Wrap<IArgList>> = <const> {
6463 C . factory . wrap ( { args, distinct } , C . factory . sourceLocation ( open , close ) ) ) ;
6564 } } ,
6665 ] ) ,
67- gImpl : ( ) => ( ) => { } ,
66+ gImpl : ( { SUBRULE , PRINT_WORD } ) => ( ast , { factory : F } ) => {
67+ F . printFilter ( ast , ( ) => {
68+ PRINT_WORD ( '(' ) ;
69+ if ( ast . val . distinct ) {
70+ PRINT_WORD ( 'distinct' ) ;
71+ }
72+ } ) ;
73+ const [ head , ...tail ] = ast . val . args ;
74+ SUBRULE ( expression , head , undefined ) ;
75+ for ( const expr of tail ) {
76+ F . printFilter ( ast , ( ) => PRINT_WORD ( ',' ) ) ;
77+ SUBRULE ( expression , expr , undefined ) ;
78+ }
79+ F . printFilter ( ast , ( ) => PRINT_WORD ( ')' ) ) ;
80+ } ,
6881} ;
6982
7083/**
7184 * [[72]](https://www.w3.org/TR/sparql11-query/#rConstructTemplate)
7285 */
73- export const expressionList : SparqlRule < 'expressionList' , Wrap < Expression [ ] > > = < const > {
86+ export const expressionList : SparqlGrammarRule < 'expressionList' , Wrap < Expression [ ] > > = < const > {
7487 name : 'expressionList' ,
7588 impl : ( { ACTION , CONSUME , MANY , OR , SUBRULE1 , SUBRULE2 } ) => C => OR ( [
7689 { ALT : ( ) => {
@@ -90,16 +103,66 @@ export const expressionList: SparqlRule<'expressionList', Wrap<Expression[]>> =
90103 return ACTION ( ( ) => C . factory . wrap ( args , C . factory . sourceLocation ( open , close ) ) ) ;
91104 } } ,
92105 ] ) ,
93- gImpl : ( ) => ( ) => '' ,
94106} ;
95107
108+ const infixOperators = new Set ( [ '||' , '&&' , '=' , '!=' , '<' , '>' , '<=' , '>=' , '+' , '-' , '*' , '/' ] ) ;
109+ const prefixOperator = new Set ( [ '!' , 'UPLUS' , 'UMINUS' ] ) ;
110+
96111/**
97112 * [[110]](https://www.w3.org/TR/sparql11-query/#rExpression)
98113 */
99114export const expression : SparqlRule < 'expression' , Expression > = < const > {
100115 name : 'expression' ,
101116 impl : ( { SUBRULE } ) => ( ) => SUBRULE ( conditionalOrExpression , undefined ) ,
102- gImpl : ( ) => ( ) => { } ,
117+ gImpl : ( { SUBRULE , PRINT_WORD } ) => ( ast , { factory : F } ) => {
118+ if ( F . isTerm ( ast ) ) {
119+ SUBRULE ( varOrTerm , ast , undefined ) ;
120+ } else {
121+ if ( ast . expressionType === 'operation' ) {
122+ if ( infixOperators . has ( ast . operator ) ) {
123+ const [ left , right ] = < [ Expression , Expression ] > ast . args ;
124+ F . printFilter ( ast , ( ) => PRINT_WORD ( '(' ) ) ;
125+ SUBRULE ( expression , left , undefined ) ;
126+ F . printFilter ( ast , ( ) => {
127+ if ( ast . operator === 'notin' ) {
128+ PRINT_WORD ( 'NOT IN' ) ;
129+ } else if ( ast . operator === 'in' ) {
130+ PRINT_WORD ( 'IN' ) ;
131+ } else {
132+ PRINT_WORD ( ast . operator ) ;
133+ }
134+ } ) ;
135+ SUBRULE ( expression , right , undefined ) ;
136+ F . printFilter ( ast , ( ) => PRINT_WORD ( ')' ) ) ;
137+ } else if ( prefixOperator . has ( ast . operator ) ) {
138+ const [ expr ] = < [ Expression ] > ast . args ;
139+ F . printFilter ( ast , ( ) => PRINT_WORD ( ast . operator ) ) ;
140+ SUBRULE ( expression , expr , undefined ) ;
141+ } else {
142+ F . printFilter ( ast , ( ) => PRINT_WORD ( ast . operator , '(' ) ) ;
143+ const [ head , ...tail ] = ast . args ;
144+ if ( head ) {
145+ SUBRULE ( expression , head , undefined ) ;
146+ }
147+ for ( const arg of tail ) {
148+ F . printFilter ( ast , ( ) => PRINT_WORD ( ast . operator , ',' ) ) ;
149+ SUBRULE ( expression , arg , undefined ) ;
150+ }
151+ }
152+ }
153+ if ( ast . expressionType === 'patternOperation' ) {
154+ const patterns = ast . args ;
155+ F . printFilter ( ast , ( ) => PRINT_WORD ( ast . operator === 'exists' ? 'EXISTS' : 'NOT EXISTS' ) ) ;
156+ SUBRULE ( groupGraphPattern , F . patternGroup ( patterns , ast . loc ) , undefined ) ;
157+ }
158+ if ( ast . expressionType === 'functionCall' ) {
159+ return SUBRULE ( iriOrFunction , ast , undefined ) ;
160+ }
161+ if ( ast . expressionType === 'aggregate' ) {
162+ return SUBRULE ( aggregate , ast , undefined ) ;
163+ }
164+ }
165+ } ,
103166} ;
104167
105168type LeftDeepBuildArgs = ( left : Expression ) => ExpressionOperation ;
@@ -403,5 +466,12 @@ export const iriOrFunction: SparqlRule<'iriOrFunction', TermIri | ExpressionFunc
403466 } ) ;
404467 return functionCall ?? iriVal ;
405468 } ,
406- gImpl : ( ) => ( ) => { } ,
469+ gImpl : ( { SUBRULE } ) => ( ast , { factory : F } ) => {
470+ if ( F . isTermIri ( ast ) ) {
471+ SUBRULE ( iri , ast , undefined ) ;
472+ } else {
473+ SUBRULE ( iri , ast . function , undefined ) ;
474+ SUBRULE ( argList , F . wrap ( { args : ast . args , distinct : ast . distinct } , ast . loc ) , undefined ) ;
475+ }
476+ } ,
407477} ;
0 commit comments