Skip to content

Commit c57ac13

Browse files
committed
use enum approach to sourceLocation
1 parent a8307cf commit c57ac13

18 files changed

Lines changed: 695 additions & 499 deletions

engines/parser-sparql-1-1/test/objectListParser.test.ts

Lines changed: 122 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { Range } from '@traqula/core';
21
import { GeneratorBuilder, RangeArithmetic } from '@traqula/core';
3-
import type { PatternBgp, SparqlContext, Triple } from '@traqula/rules-sparql-1-1';
2+
import type { PatternBgp, SparqlContext, TripleNesting } from '@traqula/rules-sparql-1-1';
43
import { CommonIRIs, TraqulaFactory, completeParseContext, lex as l, gram } from '@traqula/rules-sparql-1-1';
54
import { describe, it } from 'vitest';
65
import { objectListBuilder } from '../lib';
@@ -32,32 +31,31 @@ describe('ranges', () => {
3231

3332
describe('a SPARQL 1.1 objectList parser', () => {
3433
const F = new TraqulaFactory();
35-
const subject = F.namedNode('http://example.org/subject', undefined, F.noStringMaterialization());
36-
const predicate = F.namedNode('http://example.org/predicate', undefined, F.noStringMaterialization());
34+
const subject = F.namedNode(F.sourceLocationNoMaterialize(), 'http://example.org/subject');
35+
const predicate = F.namedNode(F.sourceLocationNoMaterialize(), 'http://example.org/predicate');
3736

38-
function generate(ast: PatternBgp, skipRanges: Range[]): string {
37+
function generate(ast: PatternBgp, origSource: string): string {
3938
const generator = GeneratorBuilder.createBuilder([
4039
gram.triplesBlock,
41-
gram.varOrTerm,
40+
gram.graphNode,
4241
gram.graphTerm,
4342
gram.var_,
4443
gram.rdfLiteral,
45-
gram.string,
4644
gram.path,
45+
gram.varOrTerm,
46+
gram.triplesNode,
47+
gram.collection,
48+
gram.blankNodePropertyList,
4749
gram.blankNode,
4850
gram.iri,
4951
gram.iriFull,
5052
gram.prefixedName,
5153
]).build();
52-
return generator.triplesBlock(ast, { factory: F, skipRanges }, undefined);
54+
return generator.triplesBlock(ast, { factory: F, origSource }, undefined);
5355
}
5456

55-
function toBgp(query: string, triples: Triple[]): PatternBgp {
56-
return F.patternBgp(triples, {
57-
start: 0,
58-
end: query.length - 1,
59-
source: query,
60-
});
57+
function toBgp(query: string, triples: TripleNesting[]): PatternBgp {
58+
return F.patternBgp(triples, F.sourceLocationSource(0, query.length));
6159
}
6260

6361
function parse(query: string, context: Partial<SparqlContext>): PatternBgp {
@@ -72,7 +70,7 @@ describe('a SPARQL 1.1 objectList parser', () => {
7270
const firstTriple = F.triple(
7371
subject,
7472
predicate,
75-
F.namedNode('dust-in-the-wind', undefined, { start: 0, end: 18 }),
73+
F.namedNode(F.sourceLocationSource(0, 18), 'dust-in-the-wind'),
7674
);
7775

7876
const tests: { query: string; ast: PatternBgp | null; name: string }[] = [{
@@ -89,7 +87,7 @@ describe('a SPARQL 1.1 objectList parser', () => {
8987
get ast() {
9088
return toBgp(this.query, [
9189
firstTriple,
92-
F.triple(subject, predicate, F.namedNode('right-now', undefined, { start: 29, end: 40 })),
90+
F.triple(subject, predicate, F.namedNode(F.sourceLocationSource(29, 40), 'right-now')),
9391
]);
9492
},
9593
}, {
@@ -100,8 +98,8 @@ describe('a SPARQL 1.1 objectList parser', () => {
10098
get ast() {
10199
return toBgp(this.query, [
102100
firstTriple,
103-
F.triple(subject, predicate, F.namedNode('right-now', undefined, { start: 29, end: 40 })),
104-
F.triple(subject, predicate, F.literalTerm('alegria', undefined, { start: 42, end: 55 })),
101+
F.triple(subject, predicate, F.namedNode(F.sourceLocationSource(29, 40), 'right-now')),
102+
F.triple(subject, predicate, F.literalTerm(F.sourceLocationSource(42, 55), 'alegria')),
105103
]);
106104
},
107105
}, {
@@ -112,7 +110,7 @@ describe('a SPARQL 1.1 objectList parser', () => {
112110
get ast() {
113111
return toBgp(this.query, [
114112
firstTriple,
115-
F.triple(subject, predicate, F.blankNode(undefined, { start: 29, end: 31 })),
113+
F.triple(subject, predicate, F.blankNode(undefined, F.sourceLocationSource(29, 31))),
116114
]);
117115
},
118116
}, {
@@ -121,138 +119,155 @@ describe('a SPARQL 1.1 objectList parser', () => {
121119
[ <right-now> "alegria" ]
122120
`,
123121
get ast() {
124-
const blankNode = F.blankNode(undefined, { start: 29, end: 54 });
122+
const blankNode = F.blankNode(undefined, F.sourceLocationNoMaterialize());
125123
return toBgp(this.query, [
126124
firstTriple,
127-
F.triple(subject, predicate, blankNode),
128-
F.triple(
125+
F.triple(subject, predicate, F.tripleCollectionBlankNodeProperties(
129126
blankNode,
130-
F.namedNode('right-now', undefined, { start: 31, end: 42 }),
131-
F.literalTerm('alegria', undefined, { start: 43, end: 52 }),
132-
),
127+
[ F.triple(
128+
blankNode,
129+
F.namedNode(F.sourceLocationSource(31, 42), 'right-now'),
130+
F.literalTerm(F.sourceLocationSource(43, 52), 'alegria'),
131+
) ],
132+
F.sourceLocationSource(29, 54),
133+
)),
133134
]);
134135
},
135136
}, {
136137
name: 'nested blankNodePropertyList',
137-
query: `<dust-in-the-wind> ,
138+
query: `<dust-in-the-wind> ,
138139
[
139140
<right-now> "alegria" ;
140141
a <http://example.org/Class> , <apple>, [ a <banana> ]
141142
]
142143
`,
143144
get ast() {
144-
const outer = F.blankNode(undefined, { start: 26, end: 128 });
145-
const outerA = F.namedNode(CommonIRIs.TYPE, undefined, { start: 68, end: 69 });
146-
const inner = F.blankNode(undefined, { start: 108, end: 122 });
147-
return toBgp(this.query, [
148-
firstTriple,
149-
F.triple(subject, predicate, outer),
145+
const outerBlank = F.blankNode(undefined, F.sourceLocationNoMaterialize());
146+
const outerA = F.namedNode(F.sourceLocationSource(67, 68), CommonIRIs.TYPE);
147+
const innerBlank = F.blankNode(undefined, F.sourceLocationNoMaterialize());
148+
149+
const propertyTriples = [
150150
F.triple(
151-
outer,
152-
F.namedNode('right-now', undefined, { start: 36, end: 47 }),
153-
F.literalTerm('alegria', undefined, { start: 48, end: 57 }),
151+
outerBlank,
152+
F.namedNode(F.sourceLocationSource(35, 46), 'right-now'),
153+
F.literalTerm(F.sourceLocationSource(47, 56), 'alegria'),
154154
),
155155
F.triple(
156-
outer,
156+
outerBlank,
157157
outerA,
158-
F.namedNode('http://example.org/Class', undefined, { start: 70, end: 96 }),
158+
F.namedNode(F.sourceLocationSource(69, 95), 'http://example.org/Class'),
159159
),
160160
F.triple(
161-
outer,
161+
outerBlank,
162162
outerA,
163-
F.namedNode('apple', undefined, { start: 99, end: 106 }),
163+
F.namedNode(F.sourceLocationSource(98, 105), 'apple'),
164164
),
165165
F.triple(
166-
outer,
166+
outerBlank,
167167
outerA,
168-
inner,
169-
),
170-
F.triple(
171-
inner,
172-
F.namedNode(CommonIRIs.TYPE, undefined, { start: 110, end: 111 }),
173-
F.namedNode('banana', undefined, { start: 112, end: 120 }),
168+
F.tripleCollectionBlankNodeProperties(innerBlank, [ F.triple(
169+
innerBlank,
170+
F.namedNode(F.sourceLocationSource(109, 110), CommonIRIs.TYPE),
171+
F.namedNode(F.sourceLocationSource(111, 119), 'banana'),
172+
) ], F.sourceLocationSource(107, 121)),
174173
),
174+
];
175+
176+
return toBgp(this.query, [
177+
firstTriple,
178+
F.triple(subject, predicate, F.tripleCollectionBlankNodeProperties(
179+
outerBlank,
180+
propertyTriples,
181+
F.sourceLocationSource(25, 127),
182+
)),
175183
]);
176184
},
177185
}, {
178186
name: 'propertyList with much blank and comments',
179-
query: `<dust-in-the-wind> ,
187+
query: `<dust-in-the-wind> ,
180188
[
181-
<right-now> "alegria" ; ;
189+
<right-now> "alegria" ; ;
182190
# More lines
183191
; ;
184192
a <http://example.org/Class> , <apple>, [ a <banana> ]
185193
]
186194
`,
187195
get ast() {
188-
const outer = F.blankNode(undefined, { start: 26, end: 164 });
189-
const outerA = F.namedNode(CommonIRIs.TYPE, undefined, { start: 104, end: 105 });
190-
const inner = F.blankNode(undefined, { start: 144, end: 158 });
191-
return toBgp(this.query, [
192-
firstTriple,
193-
F.triple(subject, predicate, outer),
196+
const outerBlank = F.blankNode(undefined, F.sourceLocationNoMaterialize());
197+
const innerBlank = F.blankNode(undefined, F.sourceLocationNoMaterialize());
198+
const outerA = F.namedNode(F.sourceLocationSource(102, 103), CommonIRIs.TYPE);
199+
200+
const outer = F.tripleCollectionBlankNodeProperties(outerBlank, [
194201
F.triple(
195-
outer,
196-
F.namedNode('right-now', undefined, { start: 36, end: 47 }),
197-
F.literalTerm('alegria', undefined, { start: 48, end: 57 }),
202+
outerBlank,
203+
F.namedNode(F.sourceLocationSource(35, 46), 'right-now'),
204+
F.literalTerm(F.sourceLocationSource(47, 56), 'alegria'),
198205
),
199206
F.triple(
200-
outer,
207+
outerBlank,
201208
outerA,
202-
F.namedNode('http://example.org/Class', undefined, { start: 106, end: 132 }),
209+
F.namedNode(F.sourceLocationSource(104, 130), 'http://example.org/Class'),
203210
),
204211
F.triple(
205-
outer,
212+
outerBlank,
206213
outerA,
207-
F.namedNode('apple', undefined, { start: 135, end: 142 }),
214+
F.namedNode(F.sourceLocationSource(133, 140), 'apple'),
208215
),
209216
F.triple(
210-
outer,
217+
outerBlank,
211218
outerA,
212-
inner,
213-
),
214-
F.triple(
215-
inner,
216-
F.namedNode(CommonIRIs.TYPE, undefined, { start: 146, end: 147 }),
217-
F.namedNode('banana', undefined, { start: 148, end: 156 }),
219+
F.tripleCollectionBlankNodeProperties(innerBlank, [
220+
F.triple(
221+
innerBlank,
222+
F.namedNode(F.sourceLocationSource(144, 145), CommonIRIs.TYPE),
223+
F.namedNode(F.sourceLocationSource(147, 154), 'banana'),
224+
),
225+
], F.sourceLocationSource(142, 156)),
218226
),
227+
], F.sourceLocationSource(25, 162));
228+
return toBgp(this.query, [
229+
firstTriple,
230+
F.triple(subject, predicate, outer),
219231
]);
220232
},
221233
}, {
222234
name: 'empty collection',
223-
query: `<dust-in-the-wind> ,
235+
query: `<dust-in-the-wind> ,
224236
( )
225237
`,
226238
get ast() {
227239
return toBgp(this.query, [
228240
firstTriple,
229-
F.triple(subject, predicate, F.namedNode(CommonIRIs.NIL, undefined, { start: 26, end: 29 })),
241+
F.triple(subject, predicate, F.namedNode(F.sourceLocationSource(25, 28), CommonIRIs.NIL)),
230242
]);
231243
},
232244
}, {
233245
name: 'connection 3 elements',
234-
query: `<dust-in-the-wind> ,
246+
query: `<dust-in-the-wind> ,
235247
( <a> [] <b> )
236248
`,
237249
get ast() {
238250
// Content blankNodes are created before list blankNodes
239-
const emptyBlank = F.blankNode(undefined, { start: 32, end: 34 });
251+
const emptyBlank = F.blankNode(undefined, F.sourceLocationSource(31, 33));
240252

241-
const outer = F.blankNode(undefined, { start: 26, end: 40 });
242-
const first = F.namedNode(CommonIRIs.FIRST, undefined, F.noStringMaterialization());
243-
const rest = F.namedNode(CommonIRIs.REST, undefined, F.noStringMaterialization());
244-
const nil = F.namedNode(CommonIRIs.NIL, undefined, F.noStringMaterialization());
245-
const rest1 = F.blankNode(undefined, F.noStringMaterialization());
246-
const rest2 = F.blankNode(undefined, F.noStringMaterialization());
247-
return toBgp(this.query, [
248-
firstTriple,
249-
F.triple(subject, predicate, outer),
250-
F.triple(outer, first, F.namedNode('a', undefined, { start: 28, end: 31 })),
251-
F.triple(outer, rest, rest1),
253+
const listHead = F.blankNode(undefined, F.sourceLocationNoMaterialize());
254+
const first = F.namedNode(F.sourceLocationNoMaterialize(), CommonIRIs.FIRST);
255+
const rest = F.namedNode(F.sourceLocationNoMaterialize(), CommonIRIs.REST);
256+
const nil = F.namedNode(F.sourceLocationNoMaterialize(), CommonIRIs.NIL);
257+
const rest1 = F.blankNode(undefined, F.sourceLocationNoMaterialize());
258+
const rest2 = F.blankNode(undefined, F.sourceLocationNoMaterialize());
259+
const listWrap = F.tripleCollectionList(listHead, [
260+
F.triple(listHead, first, F.namedNode(F.sourceLocationSource(27, 30), 'a')),
261+
F.triple(listHead, rest, rest1),
252262
F.triple(rest1, first, emptyBlank),
253263
F.triple(rest1, rest, rest2),
254-
F.triple(rest2, first, F.namedNode('b', undefined, { start: 35, end: 38 })),
264+
F.triple(rest2, first, F.namedNode(F.sourceLocationSource(34, 37), 'b')),
255265
F.triple(rest2, rest, nil),
266+
], F.sourceLocationSource(25, 39));
267+
268+
return toBgp(this.query, [
269+
firstTriple,
270+
F.triple(subject, predicate, listWrap),
256271
]);
257272
},
258273
}];
@@ -264,7 +279,7 @@ describe('a SPARQL 1.1 objectList parser', () => {
264279
F.resetBlankNodeCounter();
265280
expect(res).toEqual(test.ast);
266281

267-
const generated = generate(res, []);
282+
const generated = generate(res, test.query);
268283
expect(generated).toEqual(test.query);
269284
});
270285
}
@@ -276,19 +291,28 @@ describe('a SPARQL 1.1 objectList parser', () => {
276291
F.resetBlankNodeCounter();
277292
const res = parse(query, context);
278293
F.resetBlankNodeCounter();
279-
const toSkip = res.triples[2].object.loc!;
280-
const alterRes: PatternBgp = {
281-
...res,
282-
triples: [
283-
...res.triples.slice(0, 2),
284-
F.triple(
285-
res.triples[2].subject,
286-
res.triples[2].predicate,
287-
F.literalTerm('altered', undefined),
288-
),
289-
],
290-
};
291-
expect(generate(alterRes, [[ toSkip.start, toSkip.end ]])).toEqual(`<dust-in-the-wind> ,
294+
/* eslint-disable ts/ban-ts-comment */
295+
function alterType(curObject: object, searchType: string, patch: (current: object) => object): object {
296+
for (const [ key, value ] of Object.entries(curObject)) {
297+
if (value && typeof value === 'object') {
298+
(<Record<string, unknown>> curObject)[key] = alterType(value, searchType, patch);
299+
}
300+
}
301+
if ((<{ type?: unknown }> curObject).type === searchType) {
302+
return patch(curObject);
303+
}
304+
return curObject;
305+
}
306+
const alterRes = <PatternBgp> alterType(res, 'term', (cur) => {
307+
if (F.isTerm(cur) && F.isTermLiteral(cur) && cur.value === 'alegria') {
308+
// @ts-expect-error
309+
return F.literalTerm(F.sourceLocationNodeReplace(cur.loc.start, cur.loc.end), 'altered');
310+
}
311+
return cur;
312+
});
313+
/* eslint-enable ts/ban-ts-comment */
314+
315+
expect(generate(alterRes, query)).toEqual(`<dust-in-the-wind> ,
292316
[ <right-now> "altered" ]
293317
`);
294318
});

engines/parser-sparql-1-1/test/triplesTemplateParser.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type { SparqlContext, Triple, Wrap } from '@traqula/rules-sparql-1-1';
1+
import type { SparqlContext, TripleNesting, Wrap } from '@traqula/rules-sparql-1-1';
22
import { TraqulaFactory, completeParseContext, lex as l } from '@traqula/rules-sparql-1-1';
33
import { describe, it } from 'vitest';
44
import { triplesTemplateParserBuilder } from '../lib';
55

66
describe('a SPARQL 1.1 objectlist parser', () => {
77
const F = new TraqulaFactory();
8-
function parse(query: string, context: Partial<SparqlContext>): Wrap<Triple[]> {
8+
function parse(query: string, context: Partial<SparqlContext>): Wrap<TripleNesting[]> {
99
const parser = triplesTemplateParserBuilder.consumeToParser({
1010
tokenVocabulary: l.sparql11Tokens.build(),
1111
});

0 commit comments

Comments
 (0)