n3 2.8.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/N3Parser.js CHANGED
@@ -1446,14 +1446,16 @@ class N3Parser {
1446
1446
 
1447
1447
  // ### `parse` parses the N3 input and emits each parsed quad through the onQuad callback.
1448
1448
  parse(input, quadCallback, prefixCallback, versionCallback) {
1449
- // The second parameter accepts an object { onQuad: ..., onPrefix: ..., onComment: ...}
1449
+ // The second parameter also accepts an object of named callbacks.
1450
1450
  // As a second and third parameter it still accepts a separate quadCallback and prefixCallback for backward compatibility as well
1451
- let onQuad, onPrefix, onComment, onVersion;
1452
- if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion)) {
1451
+ let onQuad, onPrefix, onComment, onVersion, onToken, onTokenEnd;
1452
+ if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion || quadCallback.onToken || quadCallback.onTokenEnd)) {
1453
1453
  onQuad = quadCallback.onQuad;
1454
1454
  onPrefix = quadCallback.onPrefix;
1455
1455
  onComment = quadCallback.onComment;
1456
1456
  onVersion = quadCallback.onVersion;
1457
+ onToken = quadCallback.onToken;
1458
+ onTokenEnd = quadCallback.onTokenEnd;
1457
1459
  } else {
1458
1460
  onQuad = quadCallback;
1459
1461
  onPrefix = prefixCallback;
@@ -1473,36 +1475,55 @@ class N3Parser {
1473
1475
  this._expectOf = false;
1474
1476
  this._quantified = Object.create(null);
1475
1477
  this._emptyFormula = false;
1478
+ let readToken = token => {
1479
+ return this._readCallback = this._readCallback(token);
1480
+ };
1481
+
1482
+ // Comments bypass the grammar, but participate in the token lifecycle.
1483
+ if (onComment || this._lexer.comments) {
1484
+ this._lexer.comments = true;
1485
+ const readGrammarToken = readToken;
1486
+ readToken = token => {
1487
+ if (token.type !== 'comment') return readGrammarToken(token);
1488
+ if (onComment) onComment(token.value);
1489
+ return this._readCallback;
1490
+ };
1491
+ }
1492
+
1493
+ // Install observers once per parse, leaving the ordinary token path intact.
1494
+ if (onToken || onTokenEnd) {
1495
+ const consumeToken = readToken;
1496
+ readToken = token => {
1497
+ try {
1498
+ try {
1499
+ if (onToken) onToken(token);
1500
+ return consumeToken(token);
1501
+ } finally {
1502
+ if (onTokenEnd) onTokenEnd(token);
1503
+ }
1504
+ } catch (error) {
1505
+ // A consumer exception aborts this parse, including later chunks.
1506
+ this._readCallback = null;
1507
+ throw error;
1508
+ }
1509
+ };
1510
+ }
1476
1511
 
1477
- // Parse synchronously if no quad callback is given
1512
+ // Parse synchronously if no quad callback is given.
1478
1513
  if (!onQuad) {
1479
1514
  const quads = [];
1480
1515
  let error;
1481
1516
  this._callback = (e, t) => {
1482
1517
  e ? error = e : t && quads.push(t);
1483
1518
  };
1484
- this._lexer.tokenize(input).every(token => {
1485
- return this._readCallback = this._readCallback(token);
1486
- });
1519
+ this._lexer.tokenize(input).every(readToken);
1487
1520
  if (error) throw error;
1488
1521
  return quads;
1489
1522
  }
1490
- let processNextToken = (error, token) => {
1491
- if (error !== null) this._callback(error), this._callback = noop;else if (this._readCallback) this._readCallback = this._readCallback(token);
1523
+ const processNextToken = (error, token) => {
1524
+ if (error !== null) this._callback(error), this._callback = noop;else if (this._readCallback) readToken(token);
1492
1525
  };
1493
1526
 
1494
- // Enable checking for comments on every token when a commentCallback has been set
1495
- if (onComment) {
1496
- // Enable the lexer to return comments as tokens first (disabled by default)
1497
- this._lexer.comments = true;
1498
- // Patch the processNextToken function
1499
- processNextToken = (error, token) => {
1500
- if (error !== null) this._callback(error), this._callback = noop;else if (this._readCallback) {
1501
- if (token.type === 'comment') onComment(token.value);else this._readCallback = this._readCallback(token);
1502
- }
1503
- };
1504
- }
1505
-
1506
1527
  // Parse asynchronously otherwise, executing the read callback when a token arrives
1507
1528
  this._callback = onQuad;
1508
1529
  this._lexer.tokenize(input, processNextToken);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "2.8.0",
3
+ "version": "2.9.0",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
package/src/N3Parser.js CHANGED
@@ -1564,14 +1564,17 @@ export default class N3Parser {
1564
1564
 
1565
1565
  // ### `parse` parses the N3 input and emits each parsed quad through the onQuad callback.
1566
1566
  parse(input, quadCallback, prefixCallback, versionCallback) {
1567
- // The second parameter accepts an object { onQuad: ..., onPrefix: ..., onComment: ...}
1567
+ // The second parameter also accepts an object of named callbacks.
1568
1568
  // As a second and third parameter it still accepts a separate quadCallback and prefixCallback for backward compatibility as well
1569
- let onQuad, onPrefix, onComment, onVersion;
1570
- if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion)) {
1569
+ let onQuad, onPrefix, onComment, onVersion, onToken, onTokenEnd;
1570
+ if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion ||
1571
+ quadCallback.onToken || quadCallback.onTokenEnd)) {
1571
1572
  onQuad = quadCallback.onQuad;
1572
1573
  onPrefix = quadCallback.onPrefix;
1573
1574
  onComment = quadCallback.onComment;
1574
1575
  onVersion = quadCallback.onVersion;
1576
+ onToken = quadCallback.onToken;
1577
+ onTokenEnd = quadCallback.onTokenEnd;
1575
1578
  }
1576
1579
  else {
1577
1580
  onQuad = quadCallback;
@@ -1595,42 +1598,60 @@ export default class N3Parser {
1595
1598
  this._quantified = Object.create(null);
1596
1599
  this._emptyFormula = false;
1597
1600
 
1598
- // Parse synchronously if no quad callback is given
1601
+ let readToken = token => {
1602
+ return this._readCallback = this._readCallback(token);
1603
+ };
1604
+
1605
+ // Comments bypass the grammar, but participate in the token lifecycle.
1606
+ if (onComment || this._lexer.comments) {
1607
+ this._lexer.comments = true;
1608
+ const readGrammarToken = readToken;
1609
+ readToken = token => {
1610
+ if (token.type !== 'comment')
1611
+ return readGrammarToken(token);
1612
+ if (onComment) onComment(token.value);
1613
+ return this._readCallback;
1614
+ };
1615
+ }
1616
+
1617
+ // Install observers once per parse, leaving the ordinary token path intact.
1618
+ if (onToken || onTokenEnd) {
1619
+ const consumeToken = readToken;
1620
+ readToken = token => {
1621
+ try {
1622
+ try {
1623
+ if (onToken) onToken(token);
1624
+ return consumeToken(token);
1625
+ }
1626
+ finally {
1627
+ if (onTokenEnd) onTokenEnd(token);
1628
+ }
1629
+ }
1630
+ catch (error) {
1631
+ // A consumer exception aborts this parse, including later chunks.
1632
+ this._readCallback = null;
1633
+ throw error;
1634
+ }
1635
+ };
1636
+ }
1637
+
1638
+ // Parse synchronously if no quad callback is given.
1599
1639
  if (!onQuad) {
1600
1640
  const quads = [];
1601
1641
  let error;
1602
1642
  this._callback = (e, t) => { e ? (error = e) : t && quads.push(t); };
1603
- this._lexer.tokenize(input).every(token => {
1604
- return this._readCallback = this._readCallback(token);
1605
- });
1643
+ this._lexer.tokenize(input).every(readToken);
1606
1644
  if (error) throw error;
1607
1645
  return quads;
1608
1646
  }
1609
1647
 
1610
- let processNextToken = (error, token) => {
1648
+ const processNextToken = (error, token) => {
1611
1649
  if (error !== null)
1612
1650
  this._callback(error), this._callback = noop;
1613
1651
  else if (this._readCallback)
1614
- this._readCallback = this._readCallback(token);
1652
+ readToken(token);
1615
1653
  };
1616
1654
 
1617
- // Enable checking for comments on every token when a commentCallback has been set
1618
- if (onComment) {
1619
- // Enable the lexer to return comments as tokens first (disabled by default)
1620
- this._lexer.comments = true;
1621
- // Patch the processNextToken function
1622
- processNextToken = (error, token) => {
1623
- if (error !== null)
1624
- this._callback(error), this._callback = noop;
1625
- else if (this._readCallback) {
1626
- if (token.type === 'comment')
1627
- onComment(token.value);
1628
- else
1629
- this._readCallback = this._readCallback(token);
1630
- }
1631
- };
1632
- }
1633
-
1634
1655
  // Parse asynchronously otherwise, executing the read callback when a token arrives
1635
1656
  this._callback = onQuad;
1636
1657
  this._lexer.tokenize(input, processNextToken);