eyeling 1.15.4 → 1.15.6

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.
@@ -0,0 +1,138 @@
1
+ # ===================================================
2
+ # Fast Fourier Transform (FFT)
3
+ # Input sequence: (0 1 2 3 4 5 6 7)
4
+ # Numeric version with explicit complex pairs (re im)
5
+ # 8th roots of unity are baked in as constants
6
+ # ===================================================
7
+
8
+ @prefix : <http://example.org/fft8#>.
9
+ @prefix math: <http://www.w3.org/2000/10/swap/math#>.
10
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
11
+
12
+ # -------------------------------------------
13
+ # 8th roots of unity: W8^k = exp(-2*pi*i*k/8)
14
+ # represented as (re im)
15
+ # -------------------------------------------
16
+
17
+ 0 :w8 (1.0 0.0).
18
+ 1 :w8 (0.7071067811865476 -0.7071067811865476).
19
+ 2 :w8 (0.0 -1.0).
20
+ 3 :w8 (-0.7071067811865476 -0.7071067811865476).
21
+ 4 :w8 (-1.0 0.0).
22
+ 5 :w8 (-0.7071067811865476 0.7071067811865476).
23
+ 6 :w8 (0.0 1.0).
24
+ 7 :w8 (0.7071067811865476 0.7071067811865476).
25
+
26
+ # --------------------------------------------
27
+ # Complex arithmetic on explicit pairs (re im)
28
+ # --------------------------------------------
29
+
30
+ # (a+bi) + (c+di) = (a+c) + (b+d)i
31
+ {
32
+ ((?ar ?ai) (?br ?bi)) :cAdd (?cr ?ci).
33
+ } <= {
34
+ (?ar ?br) math:sum ?cr.
35
+ (?ai ?bi) math:sum ?ci.
36
+ }.
37
+
38
+ # (a+bi) * (c+di) = (ac-bd) + (ad+bc)i
39
+ {
40
+ ((?ar ?ai) (?br ?bi)) :cMul (?cr ?ci).
41
+ } <= {
42
+ (?ar ?br) math:product ?ac.
43
+ (?ai ?bi) math:product ?bd.
44
+ (?ac ?bd) math:difference ?cr.
45
+
46
+ (?ar ?bi) math:product ?ad.
47
+ (?ai ?br) math:product ?bc.
48
+ (?ad ?bc) math:sum ?ci.
49
+ }.
50
+
51
+ # --------------------------------------------------------
52
+ # Numeric radix-2 FFT evaluator
53
+ #
54
+ # ((samples...) p) :fftPair (re im)
55
+ #
56
+ # This computes X[p] for the given sample list, where p is
57
+ # in 0..7 and the primitive 8th root table above is used.
58
+ # --------------------------------------------------------
59
+
60
+ # Base case: one real sample x becomes the complex number (x 0)
61
+ {
62
+ ((?x) ?p) :fftPair (?x 0.0).
63
+ } <= {}.
64
+
65
+ # Length 2
66
+ {
67
+ ((?x0 ?x1) ?p) :fftPair ?out.
68
+ } <= {
69
+ (?p 2) math:product ?twiceP.
70
+ (?twiceP 8) math:remainder ?childP.
71
+
72
+ ((?x0) ?childP) :fftPair ?lhs.
73
+ ((?x1) ?childP) :fftPair ?rhs.
74
+
75
+ ?p :w8 ?w.
76
+ (?w ?rhs) :cMul ?tw.
77
+ (?lhs ?tw) :cAdd ?out.
78
+ }.
79
+
80
+ # Length 4
81
+ {
82
+ ((?x0 ?x1 ?x2 ?x3) ?p) :fftPair ?out.
83
+ } <= {
84
+ (?p 2) math:product ?twiceP.
85
+ (?twiceP 8) math:remainder ?childP.
86
+
87
+ ((?x0 ?x2) ?childP) :fftPair ?lhs.
88
+ ((?x1 ?x3) ?childP) :fftPair ?rhs.
89
+
90
+ ?p :w8 ?w.
91
+ (?w ?rhs) :cMul ?tw.
92
+ (?lhs ?tw) :cAdd ?out.
93
+ }.
94
+
95
+ # Length 8
96
+ {
97
+ ((?x0 ?x1 ?x2 ?x3 ?x4 ?x5 ?x6 ?x7) ?p) :fftPair ?out.
98
+ } <= {
99
+ (?p 2) math:product ?twiceP.
100
+ (?twiceP 8) math:remainder ?childP.
101
+
102
+ ((?x0 ?x2 ?x4 ?x6) ?childP) :fftPair ?lhs.
103
+ ((?x1 ?x3 ?x5 ?x7) ?childP) :fftPair ?rhs.
104
+
105
+ ?p :w8 ?w.
106
+ (?w ?rhs) :cMul ?tw.
107
+ (?lhs ?tw) :cAdd ?out.
108
+ }.
109
+
110
+ # ---------------------
111
+ # Top-level 8-point FFT
112
+ # ---------------------
113
+
114
+ {
115
+ (?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :fft8
116
+ (?y0 ?y1 ?y2 ?y3 ?y4 ?y5 ?y6 ?y7).
117
+ } <= {
118
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 0) :fftPair ?y0.
119
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 1) :fftPair ?y1.
120
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 2) :fftPair ?y2.
121
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 3) :fftPair ?y3.
122
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 4) :fftPair ?y4.
123
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 5) :fftPair ?y5.
124
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 6) :fftPair ?y6.
125
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) 7) :fftPair ?y7.
126
+ }.
127
+
128
+ # -----
129
+ # Query
130
+ # -----
131
+
132
+ {
133
+ (0 1 2 3 4 5 6 7) :fft8 ?out.
134
+ }
135
+ log:query
136
+ {
137
+ :result :fft ?out.
138
+ }.
@@ -0,0 +1,109 @@
1
+ # ===================================================
2
+ # Fast Fourier Transform (FFT)
3
+ # Input sequence: (0 1 2 3 4 5 6 7)
4
+ # Symbolic radix-2 FFT
5
+ # Complex roots of unity are represented symbolically
6
+ # ===================================================
7
+
8
+ @prefix : <http://example.org/fft8#>.
9
+ @prefix math: <http://www.w3.org/2000/10/swap/math#>.
10
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
11
+
12
+ # -------------------------------------------------
13
+ # Symbolic expression encoding
14
+ #
15
+ # sample i -> (:leaf i)
16
+ # omega^p -> (:twiddle :omega p)
17
+ # omega^p * expr -> (:mul (:twiddle :omega p) expr)
18
+ # a + b -> (:add a b)
19
+ # -------------------------------------------------
20
+
21
+ # ---------
22
+ # Base case
23
+ # ---------
24
+
25
+ # A list of length 1 is turned into a leaf node.
26
+ {
27
+ ((?i) ?root ?p ?n) :fftExpr (:leaf ?i).
28
+ } <= {}.
29
+
30
+ # ------------------------------
31
+ # FFT rule for lists of length 2
32
+ # ------------------------------
33
+
34
+ # FFT([a,b], p) =
35
+ # FFT([a], 2p mod n) + omega^p * FFT([b], 2p mod n)
36
+ {
37
+ ((?i0 ?i1) ?root ?p ?n) :fftExpr
38
+ (:add ?lhs (:mul (:twiddle ?root ?p) ?rhs)).
39
+ } <= {
40
+ (?p 2) math:product ?twiceP.
41
+ (?twiceP ?n) math:remainder ?childP.
42
+
43
+ ((?i0) ?root ?childP ?n) :fftExpr ?lhs.
44
+ ((?i1) ?root ?childP ?n) :fftExpr ?rhs.
45
+ }.
46
+
47
+ # ------------------------------
48
+ # FFT rule for lists of length 4
49
+ # ------------------------------
50
+
51
+ # Split the input into even and odd positions.
52
+ {
53
+ ((?i0 ?i1 ?i2 ?i3) ?root ?p ?n) :fftExpr
54
+ (:add ?lhs (:mul (:twiddle ?root ?p) ?rhs)).
55
+ } <= {
56
+ (?p 2) math:product ?twiceP.
57
+ (?twiceP ?n) math:remainder ?childP.
58
+
59
+ ((?i0 ?i2) ?root ?childP ?n) :fftExpr ?lhs.
60
+ ((?i1 ?i3) ?root ?childP ?n) :fftExpr ?rhs.
61
+ }.
62
+
63
+ # ------------------------------
64
+ # FFT rule for lists of length 8
65
+ # ------------------------------
66
+
67
+ # Split the input into even and odd positions.
68
+ {
69
+ ((?i0 ?i1 ?i2 ?i3 ?i4 ?i5 ?i6 ?i7) ?root ?p ?n) :fftExpr
70
+ (:add ?lhs (:mul (:twiddle ?root ?p) ?rhs)).
71
+ } <= {
72
+ (?p 2) math:product ?twiceP.
73
+ (?twiceP ?n) math:remainder ?childP.
74
+
75
+ ((?i0 ?i2 ?i4 ?i6) ?root ?childP ?n) :fftExpr ?lhs.
76
+ ((?i1 ?i3 ?i5 ?i7) ?root ?childP ?n) :fftExpr ?rhs.
77
+ }.
78
+
79
+ # ---------------------
80
+ # Top-level 8-point FFT
81
+ # ---------------------
82
+
83
+ # Evaluate the symbolic FFT at p = 0..7.
84
+ {
85
+ (?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :fft8
86
+ (?x0 ?x1 ?x2 ?x3 ?x4 ?x5 ?x6 ?x7).
87
+ } <= {
88
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 0 8) :fftExpr ?x0.
89
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 1 8) :fftExpr ?x1.
90
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 2 8) :fftExpr ?x2.
91
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 3 8) :fftExpr ?x3.
92
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 4 8) :fftExpr ?x4.
93
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 5 8) :fftExpr ?x5.
94
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 6 8) :fftExpr ?x6.
95
+ ((?a0 ?a1 ?a2 ?a3 ?a4 ?a5 ?a6 ?a7) :omega 7 8) :fftExpr ?x7.
96
+ }.
97
+
98
+ # -----
99
+ # Query
100
+ # -----
101
+
102
+ # Ask for the symbolic FFT of (0 1 2 3 4 5 6 7).
103
+ {
104
+ (0 1 2 3 4 5 6 7) :fft8 ?out.
105
+ }
106
+ log:query
107
+ {
108
+ :result :fft ?out.
109
+ }.
@@ -0,0 +1,4 @@
1
+ @prefix : <http://example.org/fft8#> .
2
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
3
+
4
+ :result :fft (("28"^^xsd:decimal "0"^^xsd:decimal) ("-4"^^xsd:decimal "9.65685424949238"^^xsd:decimal) ("-4"^^xsd:decimal "4"^^xsd:decimal) ("-4"^^xsd:decimal "1.6568542494923806"^^xsd:decimal) ("-4"^^xsd:decimal "0"^^xsd:decimal) ("-4"^^xsd:decimal "-1.6568542494923806"^^xsd:decimal) ("-4"^^xsd:decimal "-4"^^xsd:decimal) ("-4"^^xsd:decimal "-9.65685424949238"^^xsd:decimal)) .
@@ -0,0 +1,3 @@
1
+ @prefix : <http://example.org/fft8#> .
2
+
3
+ :result :fft ((:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 0) (:leaf 4))) (:mul (:twiddle :omega 0) (:add (:leaf 2) (:mul (:twiddle :omega 0) (:leaf 6))))) (:mul (:twiddle :omega 0) (:add (:add (:leaf 1) (:mul (:twiddle :omega 0) (:leaf 5))) (:mul (:twiddle :omega 0) (:add (:leaf 3) (:mul (:twiddle :omega 0) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 4) (:leaf 4))) (:mul (:twiddle :omega 2) (:add (:leaf 2) (:mul (:twiddle :omega 4) (:leaf 6))))) (:mul (:twiddle :omega 1) (:add (:add (:leaf 1) (:mul (:twiddle :omega 4) (:leaf 5))) (:mul (:twiddle :omega 2) (:add (:leaf 3) (:mul (:twiddle :omega 4) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 0) (:leaf 4))) (:mul (:twiddle :omega 4) (:add (:leaf 2) (:mul (:twiddle :omega 0) (:leaf 6))))) (:mul (:twiddle :omega 2) (:add (:add (:leaf 1) (:mul (:twiddle :omega 0) (:leaf 5))) (:mul (:twiddle :omega 4) (:add (:leaf 3) (:mul (:twiddle :omega 0) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 4) (:leaf 4))) (:mul (:twiddle :omega 6) (:add (:leaf 2) (:mul (:twiddle :omega 4) (:leaf 6))))) (:mul (:twiddle :omega 3) (:add (:add (:leaf 1) (:mul (:twiddle :omega 4) (:leaf 5))) (:mul (:twiddle :omega 6) (:add (:leaf 3) (:mul (:twiddle :omega 4) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 0) (:leaf 4))) (:mul (:twiddle :omega 0) (:add (:leaf 2) (:mul (:twiddle :omega 0) (:leaf 6))))) (:mul (:twiddle :omega 4) (:add (:add (:leaf 1) (:mul (:twiddle :omega 0) (:leaf 5))) (:mul (:twiddle :omega 0) (:add (:leaf 3) (:mul (:twiddle :omega 0) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 4) (:leaf 4))) (:mul (:twiddle :omega 2) (:add (:leaf 2) (:mul (:twiddle :omega 4) (:leaf 6))))) (:mul (:twiddle :omega 5) (:add (:add (:leaf 1) (:mul (:twiddle :omega 4) (:leaf 5))) (:mul (:twiddle :omega 2) (:add (:leaf 3) (:mul (:twiddle :omega 4) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 0) (:leaf 4))) (:mul (:twiddle :omega 4) (:add (:leaf 2) (:mul (:twiddle :omega 0) (:leaf 6))))) (:mul (:twiddle :omega 6) (:add (:add (:leaf 1) (:mul (:twiddle :omega 0) (:leaf 5))) (:mul (:twiddle :omega 4) (:add (:leaf 3) (:mul (:twiddle :omega 0) (:leaf 7))))))) (:add (:add (:add (:leaf 0) (:mul (:twiddle :omega 4) (:leaf 4))) (:mul (:twiddle :omega 6) (:add (:leaf 2) (:mul (:twiddle :omega 4) (:leaf 6))))) (:mul (:twiddle :omega 7) (:add (:add (:leaf 1) (:mul (:twiddle :omega 4) (:leaf 5))) (:mul (:twiddle :omega 6) (:add (:leaf 3) (:mul (:twiddle :omega 4) (:leaf 7)))))))) .
package/eyeling.js CHANGED
@@ -8606,6 +8606,10 @@ function assertValidQNamePrefix(prefixName, fail, tok, context = 'prefixed name'
8606
8606
  }
8607
8607
  }
8608
8608
 
8609
+ function failInvalidKeywordLikeIdent(fail, tok, name) {
8610
+ fail(`invalid_keyword(${name})`, tok);
8611
+ }
8612
+
8609
8613
  class Parser {
8610
8614
  constructor(tokens) {
8611
8615
  this.toks = tokens;
@@ -8795,7 +8799,10 @@ class Parser {
8795
8799
  if (tok2.typ === 'IriRef') {
8796
8800
  iri = resolveIriRef(tok2.value || '', this.prefixes.baseIri || '');
8797
8801
  } else if (tok2.typ === 'Ident') {
8798
- iri = this.prefixes.expandQName(tok2.value || '');
8802
+ const qn = tok2.value || '';
8803
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok2, qn);
8804
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok2, '@prefix directive IRI');
8805
+ iri = this.prefixes.expandQName(qn);
8799
8806
  } else {
8800
8807
  this.fail(`Expected IRI after @prefix, got ${tok2.toString()}`, tok2);
8801
8808
  }
@@ -8809,7 +8816,10 @@ class Parser {
8809
8816
  if (tok.typ === 'IriRef') {
8810
8817
  iri = resolveIriRef(tok.value || '', this.prefixes.baseIri || '');
8811
8818
  } else if (tok.typ === 'Ident') {
8812
- iri = tok.value || '';
8819
+ const qn = tok.value || '';
8820
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok, qn);
8821
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok, '@base directive IRI');
8822
+ iri = this.prefixes.expandQName(qn);
8813
8823
  } else {
8814
8824
  this.fail(`Expected IRI after @base, got ${tok.toString()}`, tok);
8815
8825
  }
@@ -8835,7 +8845,10 @@ class Parser {
8835
8845
  if (tok2.typ === 'IriRef') {
8836
8846
  iri = resolveIriRef(tok2.value || '', this.prefixes.baseIri || '');
8837
8847
  } else if (tok2.typ === 'Ident') {
8838
- iri = this.prefixes.expandQName(tok2.value || '');
8848
+ const qn = tok2.value || '';
8849
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok2, qn);
8850
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok2, '@prefix directive IRI');
8851
+ iri = this.prefixes.expandQName(qn);
8839
8852
  } else {
8840
8853
  this.fail(`Expected IRI after PREFIX, got ${tok2.toString()}`, tok2);
8841
8854
  }
@@ -8853,7 +8866,10 @@ class Parser {
8853
8866
  if (tok.typ === 'IriRef') {
8854
8867
  iri = resolveIriRef(tok.value || '', this.prefixes.baseIri || '');
8855
8868
  } else if (tok.typ === 'Ident') {
8856
- iri = tok.value || '';
8869
+ const qn = tok.value || '';
8870
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok, qn);
8871
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok, 'BASE directive IRI');
8872
+ iri = this.prefixes.expandQName(qn);
8857
8873
  } else {
8858
8874
  this.fail(`Expected IRI after BASE, got ${tok.toString()}`, tok);
8859
8875
  }
@@ -8905,7 +8921,7 @@ class Parser {
8905
8921
  assertValidQNamePrefix(name.split(':', 1)[0], this.fail.bind(this), tok);
8906
8922
  return internIri(this.prefixes.expandQName(name));
8907
8923
  } else {
8908
- return internIri(name);
8924
+ failInvalidKeywordLikeIdent(this.fail.bind(this), tok, name);
8909
8925
  }
8910
8926
  }
8911
8927
 
@@ -8936,10 +8952,9 @@ class Parser {
8936
8952
  dtIri = dtTok.value || '';
8937
8953
  } else if (dtTok.typ === 'Ident') {
8938
8954
  const qn = dtTok.value || '';
8939
- if (qn.includes(':')) {
8940
- assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), dtTok, 'datatype prefixed name');
8941
- dtIri = this.prefixes.expandQName(qn);
8942
- } else dtIri = qn;
8955
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), dtTok, qn);
8956
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), dtTok, 'datatype prefixed name');
8957
+ dtIri = this.prefixes.expandQName(qn);
8943
8958
  } else {
8944
8959
  this.fail(`Expected datatype after ^^, got ${dtTok.toString()}`, dtTok);
8945
8960
  }
package/lib/parser.js CHANGED
@@ -37,6 +37,10 @@ function assertValidQNamePrefix(prefixName, fail, tok, context = 'prefixed name'
37
37
  }
38
38
  }
39
39
 
40
+ function failInvalidKeywordLikeIdent(fail, tok, name) {
41
+ fail(`invalid_keyword(${name})`, tok);
42
+ }
43
+
40
44
  class Parser {
41
45
  constructor(tokens) {
42
46
  this.toks = tokens;
@@ -226,7 +230,10 @@ class Parser {
226
230
  if (tok2.typ === 'IriRef') {
227
231
  iri = resolveIriRef(tok2.value || '', this.prefixes.baseIri || '');
228
232
  } else if (tok2.typ === 'Ident') {
229
- iri = this.prefixes.expandQName(tok2.value || '');
233
+ const qn = tok2.value || '';
234
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok2, qn);
235
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok2, '@prefix directive IRI');
236
+ iri = this.prefixes.expandQName(qn);
230
237
  } else {
231
238
  this.fail(`Expected IRI after @prefix, got ${tok2.toString()}`, tok2);
232
239
  }
@@ -240,7 +247,10 @@ class Parser {
240
247
  if (tok.typ === 'IriRef') {
241
248
  iri = resolveIriRef(tok.value || '', this.prefixes.baseIri || '');
242
249
  } else if (tok.typ === 'Ident') {
243
- iri = tok.value || '';
250
+ const qn = tok.value || '';
251
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok, qn);
252
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok, '@base directive IRI');
253
+ iri = this.prefixes.expandQName(qn);
244
254
  } else {
245
255
  this.fail(`Expected IRI after @base, got ${tok.toString()}`, tok);
246
256
  }
@@ -266,7 +276,10 @@ class Parser {
266
276
  if (tok2.typ === 'IriRef') {
267
277
  iri = resolveIriRef(tok2.value || '', this.prefixes.baseIri || '');
268
278
  } else if (tok2.typ === 'Ident') {
269
- iri = this.prefixes.expandQName(tok2.value || '');
279
+ const qn = tok2.value || '';
280
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok2, qn);
281
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok2, '@prefix directive IRI');
282
+ iri = this.prefixes.expandQName(qn);
270
283
  } else {
271
284
  this.fail(`Expected IRI after PREFIX, got ${tok2.toString()}`, tok2);
272
285
  }
@@ -284,7 +297,10 @@ class Parser {
284
297
  if (tok.typ === 'IriRef') {
285
298
  iri = resolveIriRef(tok.value || '', this.prefixes.baseIri || '');
286
299
  } else if (tok.typ === 'Ident') {
287
- iri = tok.value || '';
300
+ const qn = tok.value || '';
301
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), tok, qn);
302
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), tok, 'BASE directive IRI');
303
+ iri = this.prefixes.expandQName(qn);
288
304
  } else {
289
305
  this.fail(`Expected IRI after BASE, got ${tok.toString()}`, tok);
290
306
  }
@@ -336,7 +352,7 @@ class Parser {
336
352
  assertValidQNamePrefix(name.split(':', 1)[0], this.fail.bind(this), tok);
337
353
  return internIri(this.prefixes.expandQName(name));
338
354
  } else {
339
- return internIri(name);
355
+ failInvalidKeywordLikeIdent(this.fail.bind(this), tok, name);
340
356
  }
341
357
  }
342
358
 
@@ -367,10 +383,9 @@ class Parser {
367
383
  dtIri = dtTok.value || '';
368
384
  } else if (dtTok.typ === 'Ident') {
369
385
  const qn = dtTok.value || '';
370
- if (qn.includes(':')) {
371
- assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), dtTok, 'datatype prefixed name');
372
- dtIri = this.prefixes.expandQName(qn);
373
- } else dtIri = qn;
386
+ if (!qn.includes(':')) failInvalidKeywordLikeIdent(this.fail.bind(this), dtTok, qn);
387
+ assertValidQNamePrefix(qn.split(':', 1)[0], this.fail.bind(this), dtTok, 'datatype prefixed name');
388
+ dtIri = this.prefixes.expandQName(qn);
374
389
  } else {
375
390
  this.fail(`Expected datatype after ^^, got ${dtTok.toString()}`, dtTok);
376
391
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.15.4",
3
+ "version": "1.15.6",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [