Skip to content

Commit 77c9160

Browse files
committed
introduction of localized type as a split between Node types and loc anotatio
1 parent 0bb1e80 commit 77c9160

16 files changed

Lines changed: 409 additions & 227 deletions

File tree

packages/core/lib/CoreFactory.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,32 @@ import type {
88
SourceLocationSource,
99
SourceLocationStringReplace,
1010
Node,
11+
Localized,
12+
Wrap,
1113
} from './nodeTypings';
1214

1315
export class CoreFactory {
14-
public sourceLocation(...elements: (Pick<IToken, 'startOffset' | 'endOffset'> | SourceLocation)[]): SourceLocation {
15-
const filtered =
16-
elements.filter(element => !this.isSourceLocation(element) || this.isSourceLocationSource(element));
16+
public wrap<T>(val: T, loc: SourceLocation): Wrap<T> {
17+
return { val, loc };
18+
}
19+
20+
public isLocalized(obj: unknown): obj is Localized {
21+
return typeof obj === 'object' && obj !== null && 'loc' in obj &&
22+
typeof obj.loc === 'object' && obj.loc !== null && 'sourceLocationType' in obj;
23+
}
24+
25+
public sourceLocation(...elements: (undefined | IToken | Localized)[]): SourceLocation {
26+
const filtered = <(Localized | IToken)[]> elements.filter(element =>
27+
element && (!this.isLocalized(element) || this.isSourceLocationSource(element.loc)));
1728
if (filtered.length === 0) {
1829
return this.sourceLocationNoMaterialize();
1930
}
2031
const first = filtered[0];
2132
const last = filtered.at(-1)!;
2233
return {
2334
sourceLocationType: 'source',
24-
start: this.isSourceLocationSource(first) ? first.start : first.startOffset,
25-
end: this.isSourceLocationSource(last) ? last.end : (last.endOffset! + 1),
35+
start: this.isLocalized(first) ? (<SourceLocationSource> first.loc).start : first.startOffset,
36+
end: this.isLocalized(last) ? (<SourceLocationSource> last.loc).end : (last.endOffset! + 1),
2637
};
2738
}
2839

@@ -73,12 +84,12 @@ export class CoreFactory {
7384
return this.isSourceLocation(loc) && loc.sourceLocationType === 'autoGenerate';
7485
}
7586

76-
public nodeShouldPrint(node: Node): boolean {
87+
public nodeShouldPrint(node: Localized): boolean {
7788
return this.isSourceLocationNodeReplace(node.loc) ||
7889
this.isSourceLocationNodeAutoGenerate(node.loc);
7990
}
8091

81-
public printFilter(node: Node, callback: () => void): void {
92+
public printFilter(node: Localized, callback: () => void): void {
8293
if (this.nodeShouldPrint(node)) {
8394
callback();
8495
}

packages/core/lib/generator-builder/generatorTypes.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Node } from '../nodeTypings';
1+
import type { Localized } from '../nodeTypings';
22

33
/**
44
* Type used to declare generator rules.
@@ -18,7 +18,7 @@ export type GeneratorRule<
1818
* Generation happens on a per AST node basis.
1919
* The core will implement the generation as such. If this ever changes, we will cross that bridge when we get there.
2020
*/
21-
ReturnType = any,
21+
ReturnType extends Localized = Localized,
2222
/**
2323
* Function arguments that can be given to convey the state of the current parse operation.
2424
*/
@@ -30,7 +30,7 @@ export type GeneratorRule<
3030
};
3131

3232
export interface RuleDefArg {
33-
SUBRULE: <T extends Node, U>(cstDef: GeneratorRule<any, string, T, U>, input: T, arg: U) => void;
33+
SUBRULE: <T extends Localized, U>(cstDef: GeneratorRule<any, string, T, U>, input: T, arg: U) => void;
3434
PRINT: (...args: string[]) => void;
3535
PRINT_WORD: (...args: string[]) => void;
3636
CATCHUP: (until: number) => void;

packages/core/lib/nodeTypings.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
/**
2-
* A AST node. Nodes are indexable by their types.
3-
* When generating, the SUBRULES called should be located within the current location range.
4-
*/
5-
export type Node = {
6-
type: string;
1+
export interface Localized {
72
/**
83
* Location undefined means the node does have a string representation, but it was not clarified.
94
* This happens when an AST node is patched by a client of the lib.
105
*/
116
loc: SourceLocation;
12-
};
7+
}
8+
9+
export interface Wrap<T> extends Localized {
10+
val: T;
11+
}
12+
13+
/**
14+
* A AST node. Nodes are indexable by their types.
15+
* When generating, the SUBRULES called should be located within the current location range.
16+
*/
17+
export interface Node extends Localized {
18+
type: string;
19+
}
1320

1421
export interface SourceLocationBase {
1522
sourceLocationType: string;

packages/rules-sparql-1-1/lib/RoundTripTypes.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import type { Node } from '@traqula/core';
2-
3-
export type Wrap<T> = { val: T } & Node['loc'];
1+
import type { Localized, Node } from '@traqula/core';
42

53
export type GraphRefBase = Node & {
64
type: 'graphRef';
@@ -202,7 +200,7 @@ export type PatternGraph = PatternBase & {
202200
};
203201
export type PatternUnion = PatternBase & {
204202
patternType: 'union';
205-
patterns: Pattern[];
203+
patterns: PatternGroup[];
206204
};
207205
export type BasicGraphPattern = (TripleNesting | TripleCollection)[];
208206
export type PatternBgp = PatternBase & {
@@ -267,7 +265,7 @@ export type SolutionModifierHaving = SolutionModifierBase & {
267265
};
268266
export type Ordering =
269267
| Expression
270-
| ({ descending: boolean; expression: Expression } & Pick<Node, 'loc'>);
268+
| (Localized & { descending: boolean; expression: Expression });
271269
export type SolutionModifierOrder = SolutionModifierBase & {
272270
modifierType: 'order';
273271
orderDefs: Ordering[];

packages/rules-sparql-1-1/lib/Sparql11types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { GeneratorRule, ParserRule } from '@traqula/core';
1+
import type { GeneratorRule, ParserRule, Localized } from '@traqula/core';
22
import type { TraqulaFactory } from './factory';
33

44
export type SparqlRule<
@@ -10,8 +10,8 @@ export type SparqlRule<
1010
* Type that will be returned after a correct parse of this rule.
1111
* This type will be the return type of calling SUBRULE with this grammar rule.
1212
*/
13-
ReturnType = unknown,
14-
GenInputType = ReturnType,
13+
ReturnType extends Localized = Localized,
14+
GenInputType extends Localized = ReturnType,
1515
/**
1616
* Function arguments that can be given to convey the state of the current parse operation.
1717
*/
@@ -28,7 +28,7 @@ export type SparqlGeneratorRule<
2828
* Type that will be returned after a correct parse of this rule.
2929
* This type will be the return type of calling SUBRULE with this grammar rule.
3030
*/
31-
ReturnType = unknown,
31+
ReturnType extends Localized = Localized,
3232
/**
3333
* Function arguments that can be given to convey the state of the current parse operation.
3434
*/

packages/rules-sparql-1-1/lib/factory.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import type {
5454
TermLiteralStr,
5555
TermLiteralTyped,
5656
TermVariable,
57+
TripleCollection,
5758
TripleCollectionBlankNodeProperties,
5859
TripleCollectionList,
5960
TripleNesting,
@@ -234,14 +235,18 @@ export class TraqulaFactory extends CoreFactory {
234235
subject,
235236
predicate,
236237
object,
237-
loc: loc ?? this.sourceLocation(subject.loc, predicate.loc, object.loc),
238+
loc: loc ?? this.sourceLocation(subject, predicate, object),
238239
};
239240
}
240241

241242
public isPatternGroup(x: Pattern): x is PatternGroup {
242243
return x.type === 'pattern' && x.patternType === 'group';
243244
}
244245

246+
public isPatternUnion(x: Pattern): x is PatternUnion {
247+
return x.type === 'pattern' && x.patternType === 'union';
248+
}
249+
245250
public isPattern(x: any): x is Pattern {
246251
return x.type === 'pattern';
247252
}
@@ -293,7 +298,7 @@ export class TraqulaFactory extends CoreFactory {
293298
};
294299
}
295300

296-
public patternUnion(patterns: Pattern[], loc: SourceLocation): PatternUnion {
301+
public patternUnion(patterns: PatternGroup[], loc: SourceLocation): PatternUnion {
297302
return {
298303
type: 'pattern',
299304
patternType: 'union',
@@ -360,13 +365,6 @@ export class TraqulaFactory extends CoreFactory {
360365
};
361366
}
362367

363-
public deGroupSingle(group: PatternGroup & Pattern): Pattern {
364-
if (group.patterns.length === 1) {
365-
return group.patterns[0];
366-
}
367-
return group;
368-
}
369-
370368
public aggregate(
371369
aggregation: string,
372370
distinct: boolean,
@@ -556,6 +554,10 @@ export class TraqulaFactory extends CoreFactory {
556554
};
557555
}
558556

557+
public isTripleCollection(collection: object): collection is TripleCollection {
558+
return 'type' in collection && collection.type === 'tripleCollection';
559+
}
560+
559561
public resetBlankNodeCounter(): void {
560562
this.blankNodeCounter = 0;
561563
}

packages/rules-sparql-1-1/lib/grammar/dataSetClause.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import type { RuleDefReturn } from '@traqula/core';
1+
import type { RuleDefReturn, Wrap } from '@traqula/core';
22
import type { TokenType } from 'chevrotain';
33
import * as l from '../lexer';
4-
import type { DatasetClauses, TermIri, Wrap } from '../RoundTripTypes';
4+
import type { DatasetClauses, TermIri } from '../RoundTripTypes';
55
import type { SparqlGrammarRule, SparqlRule } from '../Sparql11types';
66
import { iri } from './literals';
77

@@ -16,17 +16,12 @@ export function datasetClauseUsing<RuleName extends 'usingClause' | 'datasetClau
1616
return OR<RuleDefReturn<typeof datasetClause>>([
1717
{ ALT: () => {
1818
const iri = SUBRULE(defaultGraphClause, undefined);
19-
return ACTION(() => ({
20-
val: { named: false, value: iri },
21-
...C.factory.sourceLocation(start, iri.loc),
22-
}));
19+
return ACTION(() => C.factory.wrap({ named: false, value: iri }, C.factory.sourceLocation(start, iri)));
2320
} },
2421
{ ALT: () => {
2522
const namedClause = SUBRULE(namedGraphClause, undefined);
26-
return ACTION(() => ({
27-
val: { named: true, value: namedClause.val },
28-
...C.factory.sourceLocation(start, namedClause),
29-
}));
23+
return ACTION(() =>
24+
C.factory.wrap({ named: true, value: namedClause.val }, C.factory.sourceLocation(start, namedClause)));
3025
} },
3126
]);
3227
},
@@ -98,7 +93,7 @@ export const namedGraphClause: SparqlGrammarRule<'namedGraphClause', Wrap<TermIr
9893
impl: ({ ACTION, SUBRULE, CONSUME }) => (C) => {
9994
const named = CONSUME(l.graph.named);
10095
const iri = SUBRULE(sourceSelector, undefined);
101-
return ACTION(() => ({ val: iri, ...C.factory.sourceLocation(named, iri.loc) }));
96+
return ACTION(() => C.factory.wrap(iri, C.factory.sourceLocation(named, iri)));
10297
},
10398
};
10499

0 commit comments

Comments
 (0)