Skip to content

Commit e733c1f

Browse files
committed
feat: parse subject and predicate literals in N3 mode (#337)
1 parent 47e41f0 commit e733c1f

File tree

2 files changed

+96
-4
lines changed

2 files changed

+96
-4
lines changed

src/N3Parser.js

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,12 @@ export default class N3Parser {
237237
if (!this._n3Mode)
238238
return this._error('Unexpected literal', token);
239239

240+
// Regular literal, can still get a datatype or language
240241
if (token.prefix.length === 0) {
241242
this._literalValue = token.value;
242243
return this._completeSubjectLiteral;
243244
}
245+
// Pre-datatyped string literal (prefix stores the datatype)
244246
else
245247
this._subject = this._literal(token.value, this._namedNode(token.prefix));
246248

@@ -274,6 +276,20 @@ export default class N3Parser {
274276
case 'abbreviation':
275277
this._predicate = this.ABBREVIATIONS[token.value];
276278
break;
279+
case 'literal':
280+
if (!this._n3Mode)
281+
return this._error('Unexpected literal', token);
282+
283+
// Regular literal, can still get a datatype or language
284+
if (token.prefix.length === 0) {
285+
this._literalValue = token.value;
286+
return this._completePredicateLiteral;
287+
}
288+
// Pre-datatyped string literal (prefix stores the datatype)
289+
else
290+
this._predicate = this._literal(token.value, this._namedNode(token.prefix));
291+
292+
break;
277293
case '.':
278294
case ']':
279295
case '}':
@@ -593,10 +609,27 @@ export default class N3Parser {
593609
return { token, literal };
594610
}
595611

596-
// Completes a literal in subject position
597-
_completeSubjectLiteral(token) {
598-
this._subject = this._completeLiteral(token).literal;
599-
return this._readPredicateOrNamedGraph;
612+
_completeSubjectLiteral(tkn) {
613+
const { literal, token } = this._completeLiteral(tkn);
614+
this._subject = literal;
615+
616+
return token === null ?
617+
// If the token was consumed, continue with the rest of the input
618+
this._readPredicateOrNamedGraph :
619+
// Otherwise, consume the token now
620+
this._readPredicateOrNamedGraph(token);
621+
}
622+
623+
// Completes a literal in predicate position
624+
_completePredicateLiteral(tkn) {
625+
const { literal, token } = this._completeLiteral(tkn);
626+
this._predicate = literal;
627+
628+
return token === null ?
629+
// If the token was consumed, continue with the rest of the input
630+
this._readObject :
631+
// Otherwise, consume the token now
632+
this._readObject(token);
600633
}
601634

602635
// Completes a literal in object position

test/N3Parser-test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ describe('Parser', () => {
8181
['noturn:a', 'noturn:b', '"x"^^urn:foo'],
8282
['noturn:a', 'noturn:b', '"x"^^noturn:urn:foo']));
8383

84+
it('should not parse literals with datatype as predicate',
85+
shouldNotParse('<greaterThan> "a"^^<c> "b"^^<c>.', 'Unexpected literal on line 1.'));
86+
87+
it('should not parse literals without datatype as predicate',
88+
shouldNotParse('<greaterThan> "a" "b".', 'Unexpected literal on line 1.'));
89+
8490
it('should not parse a triple with a literal and a prefixed name type with an inexistent prefix',
8591
shouldNotParse('<a> <b> "string"^^x:z.',
8692
'Undefined prefix "x:" on line 1.', {
@@ -2254,6 +2260,59 @@ describe('Parser', () => {
22542260
));
22552261

22562262
describe('should parse literals with datatype as subject',
2263+
shouldParse(parser, '"a"^^<c> <greaterThan> <d>.',
2264+
['"a"^^http://example.org/c', 'greaterThan', 'd']
2265+
));
2266+
2267+
2268+
describe('should parse literals with datatype as subject and object',
2269+
shouldParse(parser, '"a"^^<c> <greaterThan> "b"^^<c>.',
2270+
['"a"^^http://example.org/c', 'greaterThan', '"b"^^http://example.org/c']
2271+
));
2272+
2273+
describe('should parse literals without datatype as subject and object',
2274+
shouldParse(parser, '"a" <greaterThan> "b".',
2275+
['"a"', 'greaterThan', '"b"']
2276+
));
2277+
2278+
describe('should parse literals without datatype as subject',
2279+
shouldParse(parser, '"a" <greaterThan> <b>.',
2280+
['"a"', 'greaterThan', 'b']
2281+
));
2282+
2283+
describe('should parse literals with datatype as predicate',
2284+
shouldParse(parser, '<greaterThan> "a"^^<c> "b"^^<c>.',
2285+
['greaterThan', '"a"^^http://example.org/c', '"b"^^http://example.org/c']
2286+
));
2287+
2288+
describe('should parse literals without datatype as predicate',
2289+
shouldParse(parser, '<greaterThan> "a" "b".',
2290+
['greaterThan', '"a"', '"b"']
2291+
));
2292+
2293+
describe('should parse subject, predicate, and object as integer',
2294+
shouldParse(parser, '1 1 1.',
2295+
['"1"^^http://www.w3.org/2001/XMLSchema#integer', '"1"^^http://www.w3.org/2001/XMLSchema#integer', '"1"^^http://www.w3.org/2001/XMLSchema#integer']
2296+
));
2297+
2298+
describe('should parse literals with integer as predicate',
2299+
shouldParse(parser, '<greaterThan> 1 "b".',
2300+
['greaterThan', '"1"^^http://www.w3.org/2001/XMLSchema#integer', '"b"']
2301+
));
2302+
2303+
describe('should parse literals with datatype as predicate in graph',
2304+
shouldParse(parser, '<x> <y> {<greaterThan> "a"^^<c> "b"^^<c>}.',
2305+
['x', 'y', '_:b0'],
2306+
['greaterThan', '"a"^^http://example.org/c', '"b"^^http://example.org/c', '_:b0']
2307+
));
2308+
2309+
describe('should parse literals without datatype as predicate in graph',
2310+
shouldParse(parser, '<x> <y> {<greaterThan> "a" "b"}.',
2311+
['x', 'y', '_:b0'],
2312+
['greaterThan', '"a"', '"b"', '_:b0']
2313+
));
2314+
2315+
describe('should parse literals with datatype as subject in graph',
22572316
shouldParse(parser, '<a> <b> {"a"^^<c> <greaterThan> "b"^^<c>}.',
22582317
['a', 'b', '_:b0'],
22592318
['"a"^^http://example.org/c', 'greaterThan', '"b"^^http://example.org/c', '_:b0']

0 commit comments

Comments
 (0)