Skip to content

Commit ec35367

Browse files
committed
Verify type when restoring context.
Fixes #282
1 parent 8622ab8 commit ec35367

2 files changed

Lines changed: 21 additions & 11 deletions

File tree

src/N3Parser.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ export default class N3Parser {
7474
_saveContext(type, graph, subject, predicate, object) {
7575
const n3Mode = this._n3Mode;
7676
this._contextStack.push({
77-
subject: subject, predicate: predicate, object: object,
78-
graph: graph, type: type,
77+
type,
78+
subject, predicate, object, graph,
7979
inverse: n3Mode ? this._inversePredicate : false,
8080
blankPrefix: n3Mode ? this._prefixes._ : '',
8181
quantified: n3Mode ? this._quantified : null,
@@ -94,14 +94,20 @@ export default class N3Parser {
9494

9595
// ### `_restoreContext` restores the parent context
9696
// when leaving a scope (list, blank node, formula)
97-
_restoreContext() {
98-
const context = this._contextStack.pop(), n3Mode = this._n3Mode;
97+
_restoreContext(type, token) {
98+
// Obtain the previous context
99+
const context = this._contextStack.pop();
100+
if (!context || context.type !== type)
101+
return this._error(`Unexpected ${token.type}`, token);
102+
103+
// Restore the quad of the previous context
99104
this._subject = context.subject;
100105
this._predicate = context.predicate;
101106
this._object = context.object;
102107
this._graph = context.graph;
103-
// The settings below only apply to N3 streams
104-
if (n3Mode) {
108+
109+
// Restore N3 context settings
110+
if (this._n3Mode) {
105111
this._inversePredicate = context.inverse;
106112
this._prefixes._ = context.blankPrefix;
107113
this._quantified = context.quantified;
@@ -374,7 +380,7 @@ export default class N3Parser {
374380

375381
// Restore the parent context containing this blank node
376382
const empty = this._predicate === null;
377-
this._restoreContext();
383+
this._restoreContext('blank', token);
378384
// If the blank node was the object, restore previous context and read punctuation
379385
if (this._object !== null)
380386
return this._getContextEndReader();
@@ -425,7 +431,7 @@ export default class N3Parser {
425431
break;
426432
case ')':
427433
// Closing the list; restore the parent context
428-
this._restoreContext();
434+
this._restoreContext('list', token);
429435
// If this list is contained within a parent list, return the membership quad here.
430436
// This will be `<parent list element> rdf:first <this list>.`.
431437
if (stack.length !== 0 && stack[stack.length - 1].type === 'list')
@@ -576,7 +582,7 @@ export default class N3Parser {
576582
this._emit(this._subject, this._predicate, this._object, this._graph);
577583

578584
// Restore the parent context containing this formula
579-
this._restoreContext();
585+
this._restoreContext('formula', token);
580586
// If the formula was the subject, continue reading the predicate.
581587
// If the formula was the object, read punctuation.
582588
return this._object === null ? this._readPredicate : this._getContextEndReader();
@@ -785,7 +791,7 @@ export default class N3Parser {
785791
// The list item is the remaining subejct after reading the path
786792
const item = this._subject;
787793
// Switch back to the context of the list
788-
this._restoreContext();
794+
this._restoreContext('item', token);
789795
// Output the list item
790796
this._emit(this._subject, this.RDF_FIRST, item, this._graph);
791797
}
@@ -847,7 +853,7 @@ export default class N3Parser {
847853
// Read the quad and restore the previous context
848854
const quad = this._quad(this._subject, this._predicate, this._object,
849855
this._graph || this.DEFAULTGRAPH);
850-
this._restoreContext();
856+
this._restoreContext('<<', token);
851857
// If the triple was the subject, continue by reading the predicate.
852858
if (this._subject === null) {
853859
this._subject = quad;

test/N3Parser-test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ describe('Parser', () => {
301301
shouldNotParse('<a> <b> [;].',
302302
'Expected predicate but got ; on line 1.'));
303303

304+
it('should not parse a dangling blank node closing brace',
305+
shouldNotParse('<a:a> <b:b> <c:c> ; ]',
306+
'Unexpected ] on line 1.'));
307+
304308
it('should parse a blank node with a trailing semicolon',
305309
shouldParse('<a> <b> [ <u> <v>; ].',
306310
['a', 'b', '_:b0'],

0 commit comments

Comments
 (0)